mirror of
https://github.com/go-gitea/gitea
synced 2025-09-15 21:28:15 +00: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
|
GO_DIRS := build cmd models modules routers services tests
|
||||||
WEB_DIRS := web_src/js web_src/css
|
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
|
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/*))
|
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
|
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
|
.PHONY: lint-js
|
||||||
lint-js: node_modules ## lint js files
|
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
|
$(NODE_VARS) pnpm exec vue-tsc
|
||||||
|
|
||||||
.PHONY: lint-js-fix
|
.PHONY: lint-js-fix
|
||||||
lint-js-fix: node_modules ## lint js files and fix issues
|
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
|
$(NODE_VARS) pnpm exec vue-tsc
|
||||||
|
|
||||||
.PHONY: lint-css
|
.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",
|
"@eslint-community/eslint-plugin-eslint-comments": "4.5.0",
|
||||||
"@playwright/test": "1.55.0",
|
"@playwright/test": "1.55.0",
|
||||||
"@stoplight/spectral-cli": "6.15.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",
|
"@stylistic/stylelint-plugin": "4.0.0",
|
||||||
"@types/codemirror": "5.60.16",
|
"@types/codemirror": "5.60.16",
|
||||||
"@types/dropzone": "5.7.9",
|
"@types/dropzone": "5.7.9",
|
||||||
@@ -82,24 +82,24 @@
|
|||||||
"@types/throttle-debounce": "5.0.2",
|
"@types/throttle-debounce": "5.0.2",
|
||||||
"@types/tinycolor2": "1.4.6",
|
"@types/tinycolor2": "1.4.6",
|
||||||
"@types/toastify-js": "1.12.4",
|
"@types/toastify-js": "1.12.4",
|
||||||
"@typescript-eslint/eslint-plugin": "8.43.0",
|
|
||||||
"@typescript-eslint/parser": "8.43.0",
|
"@typescript-eslint/parser": "8.43.0",
|
||||||
"@vitejs/plugin-vue": "6.0.1",
|
"@vitejs/plugin-vue": "6.0.1",
|
||||||
"@vitest/eslint-plugin": "1.3.9",
|
"@vitest/eslint-plugin": "1.3.9",
|
||||||
"eslint": "8.57.0",
|
"eslint": "9.35.0",
|
||||||
"eslint-import-resolver-typescript": "4.4.4",
|
"eslint-import-resolver-typescript": "4.4.4",
|
||||||
"eslint-plugin-array-func": "4.0.0",
|
"eslint-plugin-array-func": "5.0.2",
|
||||||
"eslint-plugin-github": "5.0.2",
|
"eslint-plugin-github": "6.0.0",
|
||||||
"eslint-plugin-import-x": "4.16.1",
|
"eslint-plugin-import-x": "4.16.1",
|
||||||
"eslint-plugin-no-jquery": "3.1.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-playwright": "2.2.2",
|
||||||
"eslint-plugin-regexp": "2.10.0",
|
"eslint-plugin-regexp": "2.10.0",
|
||||||
"eslint-plugin-sonarjs": "3.0.5",
|
"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": "10.4.0",
|
||||||
"eslint-plugin-vue-scoped-css": "2.12.0",
|
"eslint-plugin-vue-scoped-css": "2.12.0",
|
||||||
"eslint-plugin-wc": "3.0.1",
|
"eslint-plugin-wc": "3.0.1",
|
||||||
|
"globals": "16.4.0",
|
||||||
"happy-dom": "18.0.1",
|
"happy-dom": "18.0.1",
|
||||||
"markdownlint-cli": "0.45.0",
|
"markdownlint-cli": "0.45.0",
|
||||||
"material-icon-theme": "5.27.0",
|
"material-icon-theme": "5.27.0",
|
||||||
@@ -112,6 +112,7 @@
|
|||||||
"stylelint-value-no-unknown-custom-properties": "6.0.1",
|
"stylelint-value-no-unknown-custom-properties": "6.0.1",
|
||||||
"svgo": "4.0.0",
|
"svgo": "4.0.0",
|
||||||
"type-fest": "4.41.0",
|
"type-fest": "4.41.0",
|
||||||
|
"typescript-eslint": "8.43.0",
|
||||||
"updates": "16.7.0",
|
"updates": "16.7.0",
|
||||||
"vite-string-plugin": "1.4.6",
|
"vite-string-plugin": "1.4.6",
|
||||||
"vitest": "3.2.4",
|
"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' {
|
declare module '@techknowlogick/license-checker-webpack-plugin' {
|
||||||
const plugin: any;
|
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
|
'@mcaptcha/vanilla-glue', // breaking changes in rc versions need to be handled
|
||||||
'@stylistic/eslint-plugin-js', // need to migrate to eslint 9
|
'@stylistic/eslint-plugin-js', // need to migrate to eslint 9
|
||||||
'cropperjs', // need to migrate to v2 but v2 is not compatible with v1
|
'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
|
'tailwindcss', // need to migrate
|
||||||
],
|
],
|
||||||
} satisfies Config;
|
} satisfies Config;
|
||||||
|
@@ -153,7 +153,7 @@ export default defineComponent({
|
|||||||
return -1;
|
return -1;
|
||||||
},
|
},
|
||||||
getActiveItem() {
|
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
|
// @ts-expect-error - el is unknown type
|
||||||
return (el && el.length) ? el[0] : null;
|
return (el && el.length) ? el[0] : null;
|
||||||
},
|
},
|
||||||
|
@@ -4,7 +4,7 @@ import {pathEscapeSegments} from '../utils/url.ts';
|
|||||||
import {createElementFromHTML} from '../utils/dom.ts';
|
import {createElementFromHTML} from '../utils/dom.ts';
|
||||||
import {html} from '../utils/html.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({
|
const store = reactive({
|
||||||
rootFiles: [],
|
rootFiles: [],
|
||||||
selectedItem: props.treePath,
|
selectedItem: props.treePath,
|
||||||
|
@@ -19,7 +19,7 @@ type EditorConfig = {
|
|||||||
trim_trailing_whitespace?: boolean,
|
trim_trailing_whitespace?: boolean,
|
||||||
insert_final_newline?: boolean,
|
insert_final_newline?: boolean,
|
||||||
root?: boolean,
|
root?: boolean,
|
||||||
}
|
};
|
||||||
|
|
||||||
const languagesByFilename: Record<string, string> = {};
|
const languagesByFilename: Record<string, string> = {};
|
||||||
const languagesByExt: Record<string, string> = {};
|
const languagesByExt: Record<string, string> = {};
|
||||||
|
@@ -112,7 +112,7 @@ function onHidePanelClick(el: HTMLElement, e: MouseEvent) {
|
|||||||
export type ElementWithAssignableProperties = {
|
export type ElementWithAssignableProperties = {
|
||||||
getAttribute: (name: string) => string | null;
|
getAttribute: (name: string) => string | null;
|
||||||
setAttribute: (name: string, value: string) => void;
|
setAttribute: (name: string, value: string) => void;
|
||||||
} & Record<string, any>
|
} & Record<string, any>;
|
||||||
|
|
||||||
export function assignElementProperty(el: ElementWithAssignableProperties, kebabName: string, val: string) {
|
export function assignElementProperty(el: ElementWithAssignableProperties, kebabName: string, val: string) {
|
||||||
const camelizedName = camelize(kebabName);
|
const camelizedName = camelize(kebabName);
|
||||||
|
@@ -9,7 +9,7 @@ type ConfirmModalOptions = {
|
|||||||
header?: string;
|
header?: string;
|
||||||
content?: string;
|
content?: string;
|
||||||
confirmButtonColor?: 'primary' | 'red' | 'green' | 'blue';
|
confirmButtonColor?: 'primary' | 'red' | 'green' | 'blue';
|
||||||
}
|
};
|
||||||
|
|
||||||
export function createConfirmModal({header = '', content = '', confirmButtonColor = 'primary'}:ConfirmModalOptions = {}): HTMLElement {
|
export function createConfirmModal({header = '', content = '', confirmButtonColor = 'primary'}:ConfirmModalOptions = {}): HTMLElement {
|
||||||
const headerHtml = header ? html`<div class="header">${header}</div>` : '';
|
const headerHtml = header ? html`<div class="header">${header}</div>` : '';
|
||||||
|
@@ -4,7 +4,7 @@ type CropperOpts = {
|
|||||||
container: HTMLElement,
|
container: HTMLElement,
|
||||||
imageSource: HTMLImageElement,
|
imageSource: HTMLImageElement,
|
||||||
fileInput: HTMLInputElement,
|
fileInput: HTMLInputElement,
|
||||||
}
|
};
|
||||||
|
|
||||||
async function initCompCropper({container, fileInput, imageSource}: CropperOpts) {
|
async function initCompCropper({container, fileInput, imageSource}: CropperOpts) {
|
||||||
const {default: Cropper} = await import(/* webpackChunkName: "cropperjs" */'cropperjs');
|
const {default: Cropper} = await import(/* webpackChunkName: "cropperjs" */'cropperjs');
|
||||||
|
@@ -169,7 +169,7 @@ test('EditorMarkdown', () => {
|
|||||||
type ValueWithCursor = string | {
|
type ValueWithCursor = string | {
|
||||||
value: string;
|
value: string;
|
||||||
pos: number;
|
pos: number;
|
||||||
}
|
};
|
||||||
const testInput = (input: ValueWithCursor, result: ValueWithCursor) => {
|
const testInput = (input: ValueWithCursor, result: ValueWithCursor) => {
|
||||||
const intputValue = typeof input === 'string' ? input : input.value;
|
const intputValue = typeof input === 'string' ? input : input.value;
|
||||||
const inputPos = typeof input === 'string' ? intputValue.length : input.pos;
|
const inputPos = typeof input === 'string' ? intputValue.length : input.pos;
|
||||||
|
@@ -18,7 +18,7 @@ type TextareaValueSelection = {
|
|||||||
value: string;
|
value: string;
|
||||||
selStart: number;
|
selStart: number;
|
||||||
selEnd: number;
|
selEnd: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
function handleIndentSelection(textarea: HTMLTextAreaElement, e: KeyboardEvent) {
|
function handleIndentSelection(textarea: HTMLTextAreaElement, e: KeyboardEvent) {
|
||||||
const selStart = textarea.selectionStart;
|
const selStart = textarea.selectionStart;
|
||||||
@@ -65,14 +65,14 @@ function handleIndentSelection(textarea: HTMLTextAreaElement, e: KeyboardEvent)
|
|||||||
type MarkdownHandleIndentionResult = {
|
type MarkdownHandleIndentionResult = {
|
||||||
handled: boolean;
|
handled: boolean;
|
||||||
valueSelection?: TextareaValueSelection;
|
valueSelection?: TextareaValueSelection;
|
||||||
}
|
};
|
||||||
|
|
||||||
type TextLinesBuffer = {
|
type TextLinesBuffer = {
|
||||||
lines: string[];
|
lines: string[];
|
||||||
lengthBeforePosLine: number;
|
lengthBeforePosLine: number;
|
||||||
posLineIndex: number;
|
posLineIndex: number;
|
||||||
inlinePos: number
|
inlinePos: number
|
||||||
}
|
};
|
||||||
|
|
||||||
export function textareaSplitLines(value: string, pos: number): TextLinesBuffer {
|
export function textareaSplitLines(value: string, pos: number): TextLinesBuffer {
|
||||||
const lines = value.split('\n');
|
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
|
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.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
const labelId = item.getAttribute('data-label-id');
|
const labelId = item.getAttribute('data-label-id');
|
||||||
|
@@ -4,13 +4,13 @@ type Processor = (el: HTMLElement) => string | HTMLElement | void;
|
|||||||
|
|
||||||
type Processors = {
|
type Processors = {
|
||||||
[tagName: string]: Processor;
|
[tagName: string]: Processor;
|
||||||
}
|
};
|
||||||
|
|
||||||
type ProcessorContext = {
|
type ProcessorContext = {
|
||||||
elementIsFirst: boolean;
|
elementIsFirst: boolean;
|
||||||
elementIsLast: boolean;
|
elementIsLast: boolean;
|
||||||
listNestingLevel: number;
|
listNestingLevel: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
function prepareProcessors(ctx:ProcessorContext): Processors {
|
function prepareProcessors(ctx:ProcessorContext): Processors {
|
||||||
const processors: Processors = {
|
const processors: Processors = {
|
||||||
|
@@ -15,7 +15,7 @@ export type DiffTreeEntry = {
|
|||||||
Children: DiffTreeEntry[],
|
Children: DiffTreeEntry[],
|
||||||
FileIcon: string,
|
FileIcon: string,
|
||||||
ParentEntry?: DiffTreeEntry,
|
ParentEntry?: DiffTreeEntry,
|
||||||
}
|
};
|
||||||
|
|
||||||
type DiffFileTreeData = {
|
type DiffFileTreeData = {
|
||||||
TreeRoot: DiffTreeEntry,
|
TreeRoot: DiffTreeEntry,
|
||||||
@@ -28,7 +28,7 @@ type DiffFileTree = {
|
|||||||
fullNameMap?: Record<string, DiffTreeEntry>
|
fullNameMap?: Record<string, DiffTreeEntry>
|
||||||
fileTreeIsVisible: boolean;
|
fileTreeIsVisible: boolean;
|
||||||
selectedItem: string;
|
selectedItem: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
let diffTreeStoreReactive: Reactive<DiffFileTree>;
|
let diffTreeStoreReactive: Reactive<DiffFileTree>;
|
||||||
export function diffTreeStore() {
|
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 = $;
|
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
|
// 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:
|
// * 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)
|
// * in the "filter" function: ('[data-value="'+value+'"]').addClass(className.filtered)
|
||||||
|
@@ -15,7 +15,7 @@ type ToastLevels = {
|
|||||||
background: string,
|
background: string,
|
||||||
duration: number,
|
duration: number,
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const levels: ToastLevels = {
|
const levels: ToastLevels = {
|
||||||
info: {
|
info: {
|
||||||
@@ -40,7 +40,7 @@ type ToastOpts = {
|
|||||||
preventDuplicates?: boolean | string,
|
preventDuplicates?: boolean | string,
|
||||||
} & Options;
|
} & Options;
|
||||||
|
|
||||||
type ToastifyElement = HTMLElement & {_giteaToastifyInstance?: Toast };
|
type ToastifyElement = HTMLElement & {_giteaToastifyInstance?: Toast};
|
||||||
|
|
||||||
/** See https://github.com/apvarun/toastify-js#api for options */
|
/** 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 {
|
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 file content
|
||||||
render: (container: HTMLElement, fileUrl: string, options?: any) => Promise<void>;
|
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.
|
// 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
|
// 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;
|
const className = Array.isArray(classNames) ? classNames.join(' ') : classNames;
|
||||||
if (!(name in svgs)) throw new Error(`Unknown SVG icon: ${name}`);
|
if (!(name in svgs)) throw new Error(`Unknown SVG icon: ${name}`);
|
||||||
if (size === 16 && !className) return svgs[name];
|
if (size === 16 && !className) return svgs[name];
|
||||||
|
@@ -4,7 +4,7 @@ export type MentionValue = {
|
|||||||
name: string,
|
name: string,
|
||||||
fullname: string,
|
fullname: string,
|
||||||
avatar: string,
|
avatar: string,
|
||||||
}
|
};
|
||||||
|
|
||||||
export type Config = {
|
export type Config = {
|
||||||
appUrl: string,
|
appUrl: string,
|
||||||
@@ -20,7 +20,7 @@ export type Config = {
|
|||||||
mentionValues?: MentionValue[],
|
mentionValues?: MentionValue[],
|
||||||
mermaidMaxSourceCharacters: number,
|
mermaidMaxSourceCharacters: number,
|
||||||
i18n: Record<string, string>,
|
i18n: Record<string, string>,
|
||||||
}
|
};
|
||||||
|
|
||||||
export type IntervalId = ReturnType<typeof setInterval>;
|
export type IntervalId = ReturnType<typeof setInterval>;
|
||||||
|
|
||||||
@@ -35,21 +35,21 @@ export type RequestOpts = {
|
|||||||
export type RepoOwnerPathInfo = {
|
export type RepoOwnerPathInfo = {
|
||||||
ownerName: string,
|
ownerName: string,
|
||||||
repoName: string,
|
repoName: string,
|
||||||
}
|
};
|
||||||
|
|
||||||
export type IssuePathInfo = {
|
export type IssuePathInfo = {
|
||||||
ownerName: string,
|
ownerName: string,
|
||||||
repoName: string,
|
repoName: string,
|
||||||
pathType: string,
|
pathType: string,
|
||||||
indexString?: string,
|
indexString?: string,
|
||||||
}
|
};
|
||||||
|
|
||||||
export type IssuePageInfo = {
|
export type IssuePageInfo = {
|
||||||
repoLink: string,
|
repoLink: string,
|
||||||
repoId: number,
|
repoId: number,
|
||||||
issueNumber: number,
|
issueNumber: number,
|
||||||
issueDependencySearchType: string,
|
issueDependencySearchType: string,
|
||||||
}
|
};
|
||||||
|
|
||||||
export type Issue = {
|
export type Issue = {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -65,6 +65,6 @@ export type Issue = {
|
|||||||
export type FomanticInitFunction = {
|
export type FomanticInitFunction = {
|
||||||
settings?: Record<string, any>,
|
settings?: Record<string, any>,
|
||||||
(...args: any[]): any,
|
(...args: any[]): any,
|
||||||
}
|
};
|
||||||
|
|
||||||
export type GitRefType = 'branch' | 'tag';
|
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 ElementArg = Element | string | ArrayLikeIterable<Element> | ReturnType<typeof $>;
|
||||||
type ElementsCallback<T extends Element> = (el: T) => Promisable<any>;
|
type ElementsCallback<T extends Element> = (el: T) => Promisable<any>;
|
||||||
type ElementsCallbackWithArgs = (el: Element, ...args: any[]) => 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> {
|
function elementsCall(el: ElementArg, func: ElementsCallbackWithArgs, ...args: any[]): ArrayLikeIterable<Element> {
|
||||||
if (typeof el === 'string' || el instanceof String) {
|
if (typeof el === 'string' || el instanceof String) {
|
||||||
@@ -322,7 +322,7 @@ export function createElementFromHTML<T extends HTMLElement>(htmlString: string)
|
|||||||
return div.firstChild as T;
|
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);
|
const el = document.createElement(tagName);
|
||||||
for (const [key, value] of Object.entries(attrs || {})) {
|
for (const [key, value] of Object.entries(attrs || {})) {
|
||||||
if (value === undefined || value === null) continue;
|
if (value === undefined || value === null) continue;
|
||||||
|
@@ -117,7 +117,7 @@ test('GlobCompiler', async () => {
|
|||||||
for (const c of golangCases) {
|
for (const c of golangCases) {
|
||||||
const compiled = globCompile(c.pattern, c.separators);
|
const compiled = globCompile(c.pattern, c.separators);
|
||||||
const msg = `pattern: ${c.pattern}, input: ${c.input}, separators: ${c.separators || '(none)'}, compiled: ${compiled.regexpPattern}`;
|
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);
|
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;
|
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 (typeof s === 'string') {
|
||||||
if (tmplParts.length !== 0) throw new Error("either htmlRaw('str') or htmlRaw`tmpl`");
|
if (tmplParts.length !== 0) throw new Error("either htmlRaw('str') or htmlRaw`tmpl`");
|
||||||
return new rawObject(s);
|
return new rawObject(s);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
type PngChunk = {
|
type PngChunk = {
|
||||||
name: string,
|
name: string,
|
||||||
data: Uint8Array,
|
data: Uint8Array,
|
||||||
}
|
};
|
||||||
|
|
||||||
export async function pngChunks(blob: Blob): Promise<PngChunk[]> {
|
export async function pngChunks(blob: Blob): Promise<PngChunk[]> {
|
||||||
const uint8arr = new Uint8Array(await blob.arrayBuffer());
|
const uint8arr = new Uint8Array(await blob.arrayBuffer());
|
||||||
@@ -27,7 +27,7 @@ export async function pngChunks(blob: Blob): Promise<PngChunk[]> {
|
|||||||
type ImageInfo = {
|
type ImageInfo = {
|
||||||
width?: number,
|
width?: number,
|
||||||
dppx?: number,
|
dppx?: number,
|
||||||
}
|
};
|
||||||
|
|
||||||
/** decode a image and try to obtain width and dppx. It will never throw but instead
|
/** decode a image and try to obtain width and dppx. It will never throw but instead
|
||||||
* return default values. */
|
* return default values. */
|
||||||
|
@@ -47,11 +47,11 @@ export type DayData = {
|
|||||||
additions: number,
|
additions: number,
|
||||||
deletions: number,
|
deletions: number,
|
||||||
commits: number,
|
commits: number,
|
||||||
}
|
};
|
||||||
|
|
||||||
export type DayDataObject = {
|
export type DayDataObject = {
|
||||||
[timestamp: string]: DayData,
|
[timestamp: string]: DayData,
|
||||||
}
|
};
|
||||||
|
|
||||||
export function fillEmptyStartDaysWithZeroes(startDays: number[], data: DayDataObject): DayData[] {
|
export function fillEmptyStartDaysWithZeroes(startDays: number[], data: DayDataObject): DayData[] {
|
||||||
const result: Record<string, any> = {};
|
const result: Record<string, any> = {};
|
||||||
|
Reference in New Issue
Block a user