chore: migrate eslint 9 (#7588)

#### What type of PR is this?

/area ui
/kind cleanup

#### What this PR does / why we need it:

Migrate to ESLint 9, use flat config file, and simplify ESLint configuration.

Now, linting for all packages will be managed by the configuration in the project root directory.

#### Does this PR introduce a user-facing change?

```release-note
None
```
pull/7589/head
Ryan Wang 2025-06-25 08:37:20 +08:00 committed by GitHub
parent 0addf79aec
commit 1826c7dcbb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
51 changed files with 633 additions and 422 deletions

View File

@ -1,25 +0,0 @@
/* eslint-env node */
require("@rushstack/eslint-patch/modern-module-resolution");
module.exports = {
root: true,
extends: [
"plugin:vue/vue3-recommended",
"eslint:recommended",
"@vue/eslint-config-typescript/recommended",
"@vue/eslint-config-prettier",
],
env: {
node: true,
"vue/setup-compiler-macros": true,
},
rules: {
"vue/multi-word-component-names": 0,
"@typescript-eslint/ban-ts-comment": 0,
"vue/no-v-html": 0,
},
ignorePatterns: ["!.storybook", "packages/api-client"],
parserOptions: {
ecmaVersion: "latest",
},
};

View File

@ -1,4 +1,4 @@
<script setup lang="tsx">
<script setup lang="ts">
import type { OwnerInfo } from "@halo-dev/api-client";
import { VAvatar } from "@halo-dev/components";

View File

@ -118,7 +118,6 @@ export function convertCategoryTreeToCategory(
): Category {
const childNames = categoryTree.children.map((child) => child.metadata.name);
// eslint-disable-next-line
const { children: _, ...categoryWithoutChildren } = categoryTree;
return {

View File

@ -96,7 +96,7 @@ async function handleChange(value: string) {
queryClient.invalidateQueries({
queryKey: Q_KEY(extensionPointDefinitionName),
});
} catch (error) {
} catch (_) {
Toast.error(t("core.common.toast.save_failed_and_retry"));
} finally {
isSubmitting.value = false;

View File

@ -36,7 +36,9 @@ export function useUserFetch(options?: {
};
onMounted(() => {
fetchOnMounted && handleFetchUsers();
if (fetchOnMounted) {
handleFetchUsers();
}
});
return {

54
ui/eslint.config.ts Normal file
View File

@ -0,0 +1,54 @@
import pluginVitest from "@vitest/eslint-plugin";
import skipFormatting from "@vue/eslint-config-prettier/skip-formatting";
import {
defineConfigWithVueTs,
vueTsConfigs,
} from "@vue/eslint-config-typescript";
import pluginVue from "eslint-plugin-vue";
export default defineConfigWithVueTs(
{
name: "app/global-ignores",
ignores: ["**/dist/**", "**/node_modules/**", "packages/api-client/src/"],
},
pluginVue.configs["flat/recommended"],
vueTsConfigs.recommended,
{
name: "app/base",
files: ["**/*.{ts,mts,tsx,vue}"],
rules: {
"vue/multi-word-component-names": 0,
"@typescript-eslint/ban-ts-comment": 0,
"vue/no-v-html": 0,
"@typescript-eslint/no-unused-vars": [
"error",
{
args: "all",
argsIgnorePattern: "^_",
caughtErrors: "all",
caughtErrorsIgnorePattern: "^_",
destructuredArrayIgnorePattern: "^_",
varsIgnorePattern: "^_",
ignoreRestSiblings: true,
},
],
},
},
{
name: "app/config-files",
files: ["**/*.config.{js,cjs}"],
rules: {
"@typescript-eslint/no-require-imports": "off",
},
},
{
...pluginVitest.configs.recommended,
files: ["**/__tests__/*"],
},
skipFormatting
);

View File

@ -18,10 +18,9 @@
"test:unit:ui": "vitest --watch --ui",
"test:unit:coverage": "vitest run --coverage",
"typecheck": "vue-tsc --noEmit -p tsconfig.app.json --composite false && pnpm run typecheck:packages",
"lint": "eslint \"./src\" \"./console-src\" \"./uc-src\" --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --ignore-path .gitignore --max-warnings=0 -f html -o build/lint-result/index.html && pnpm run lint:packages",
"lint": "eslint . --max-warnings=0 -f html -o build/lint-result/index.html",
"prettier": "prettier --write \"./{src,uc-src,console-src}/**/*.{vue,js,jsx,ts,tsx,css,scss,json,yml,yaml,html}\" && pnpm run prettier:packages",
"typecheck:packages": "pnpm --parallel --filter \"./packages/**\" run typecheck",
"lint:packages": "pnpm --parallel --filter \"./packages/**\" lint",
"prettier:packages": "pnpm --parallel --filter \"./packages/**\" prettier",
"test:unit:packages": "pnpm --parallel --filter \"./packages/**\" run test:unit"
},
@ -29,7 +28,7 @@
"*.{vue,js,jsx,ts,tsx,css,scss,json,yml,yaml,html}": [
"prettier --write"
],
"*.{js,ts,vue,tsx,jsx}": [
"*.{ts,mts,tsx,vue}": [
"eslint --fix --max-warnings=0"
]
},
@ -113,7 +112,6 @@
"@iconify/json": "^2.2.343",
"@intlify/unplugin-vue-i18n": "^6.0.8",
"@number-flow/vue": "^0.4.8",
"@rushstack/eslint-patch": "^1.3.2",
"@tailwindcss/aspect-ratio": "^0.4.2",
"@tailwindcss/container-queries": "^0.1.0",
"@tailwindcss/forms": "^0.5.7",
@ -126,17 +124,18 @@
"@types/randomstring": "^1.1.8",
"@types/ua-parser-js": "^0.7.39",
"@typescript/native-preview": "7.0.0-dev.20250619.1",
"@vitest/eslint-plugin": "^1.2.7",
"@vitejs/plugin-vue": "^6.0.0",
"@vitejs/plugin-vue-jsx": "^5.0.0",
"@vitest/ui": "^3.1.4",
"@vue/compiler-sfc": "^3.5.16",
"@vue/eslint-config-prettier": "^7.1.0",
"@vue/eslint-config-typescript": "^11.0.3",
"@vue/eslint-config-prettier": "^10.2.0",
"@vue/eslint-config-typescript": "^14.5.0",
"@vue/test-utils": "^2.4.6",
"@vue/tsconfig": "^0.5.1",
"autoprefixer": "^10.4.14",
"c8": "^7.12.0",
"eslint": "^8.43.0",
"eslint": "^9.22.0",
"eslint-plugin-vue": "^9.33.0",
"husky": "^8.0.3",
"js-yaml": "^4.1.0",

View File

@ -1,2 +0,0 @@
dist/*
node_modules/*

View File

@ -1,3 +0,0 @@
module.exports = {
extends: ["../../.eslintrc.cjs"],
};

View File

@ -1 +0,0 @@
.storybook

View File

@ -1,3 +0,0 @@
module.exports = {
extends: ["../../.eslintrc.cjs", "plugin:storybook/recommended"],
};

View File

@ -1,4 +1,3 @@
/* eslint-disable storybook/no-uninstalled-addons */
import type { StorybookConfig } from "@storybook/vue3-vite";
const config: StorybookConfig = {

View File

@ -18,7 +18,6 @@
"test:unit:ui": "vitest --watch --ui",
"test:unit:coverage": "vitest run --coverage",
"typecheck": "vue-tsc --noEmit -p tsconfig.app.json --composite false",
"lint": "eslint ./src --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts",
"prettier": "prettier --write './src/**/*.{vue,js,jsx,ts,tsx,css,scss,json,yml,yaml,html}'",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
@ -52,7 +51,6 @@
"@storybook/testing-library": "^0.0.14-next.2",
"@storybook/vue3": "^7.6.3",
"@storybook/vue3-vite": "^7.6.3",
"eslint-plugin-storybook": "^0.6.15",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"storybook": "^7.6.3"

View File

@ -43,7 +43,7 @@ const loadImage = async (isInit: boolean) => {
reject(err);
};
});
} catch (e) {
} catch (_) {
error.value = true;
} finally {
isLoading.value = false;

View File

@ -52,10 +52,13 @@ const dialog: DialogEntry = (userProps: DialogProps) => {
props
);
hostContainer.firstElementChild &&
if (hostContainer.firstElementChild) {
container.appendChild(hostContainer.firstElementChild);
}
vnode.component?.props && (vnode.component.props.visible = true);
if (vnode.component?.props) {
vnode.component.props.visible = true;
}
if (vnode?.props) {
vnode.props.onClose = () => {

View File

@ -1,6 +0,0 @@
module.exports = {
extends: ["../../.eslintrc.cjs"],
rules: {
"@typescript-eslint/no-explicit-any": "off",
},
};

View File

@ -31,7 +31,6 @@
"scripts": {
"build": "vite build --config ./vite.lib.config.ts",
"dev": "vite",
"lint": "eslint ./src --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts",
"prettier": "prettier --write './src/**/*.{vue,js,jsx,ts,tsx,css,scss,json,yml,yaml,html}'",
"release": "release-it",
"test:unit:coverage": "vitest run --environment jsdom --coverage",

View File

@ -8,6 +8,7 @@ export interface Option {
value: string;
}
const props = defineProps<{
// eslint-disable-next-line @typescript-eslint/no-explicit-any
container?: any;
containerClass?: string;
options: Option[];

View File

@ -41,7 +41,7 @@ const updateIndent = (tr: Transaction, type: IndentType): Transaction => {
return tr;
}
const { from, to } = selection;
doc.nodesBetween(from, to, (node, pos) => {
doc.nodesBetween(from, to, (_node, pos) => {
if (from - to == 0 && type === "indent") {
tr.insertText(" ", from, to);
return false;
@ -111,6 +111,7 @@ export interface CodeBlockOptions {
* @default {}
* @example { class: 'foo' }
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
HTMLAttributes: Record<string, any>;
/**

View File

@ -66,6 +66,7 @@ const getColumnsNodeTypes = (
type ColOperateType = "addBefore" | "addAfter" | "delete";
const addOrDeleteCol = (
// eslint-disable-next-line @typescript-eslint/no-explicit-any
dispatch: any,
state: EditorState,
type: ColOperateType
@ -103,6 +104,7 @@ const addOrDeleteCol = (
colsJSON.attrs.cols = colsJSON.content.length;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
colsJSON.content.forEach((colJSON: any, index: number) => {
colJSON.attrs.index = index;
});
@ -110,7 +112,7 @@ const addOrDeleteCol = (
const nextCols = PMNode.fromJSON(state.schema, colsJSON);
let nextSelectPos = maybeColumns.pos;
nextCols.content.forEach((col, pos, index) => {
nextCols.content.forEach((col, _pos, index) => {
if (index < nextIndex) {
nextSelectPos += col.nodeSize;
}
@ -130,6 +132,7 @@ const addOrDeleteCol = (
};
type GotoColType = "before" | "after";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const gotoCol = (state: EditorState, dispatch: any, type: GotoColType) => {
const maybeColumns = findParentNode(
(node) => node.type.name === Columns.name
@ -151,7 +154,7 @@ const gotoCol = (state: EditorState, dispatch: any, type: GotoColType) => {
}
let nextSelectPos = maybeColumns.pos;
cols.content.forEach((col, pos, index) => {
cols.content.forEach((col, _pos, index) => {
if (index < nextIndex) {
nextSelectPos += col.nodeSize;
}

View File

@ -47,6 +47,7 @@ export default Extension.create({
let popup: Instance[];
return {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
onStart: (props: Record<string, any>) => {
component = new VueRenderer(CommandsView, {
props,
@ -68,6 +69,7 @@ export default Extension.create({
});
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
onUpdate(props: Record<string, any>) {
component.updateProps(props);
@ -80,6 +82,7 @@ export default Extension.create({
});
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
onKeyDown(props: Record<string, any>) {
if (props.event.key === "Escape") {
popup[0].hide();

View File

@ -33,6 +33,7 @@ let draggableHandleDom: HTMLElement | null = null;
let currEditorView: EditorView;
let activeNode: ActiveNode | null = null;
let activeSelection: NodeSelection | null = null;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let mouseleaveTimer: any;
let dragging = false;
let hoverOrClickDragItem = false;
@ -161,6 +162,7 @@ const handleDragStartEvent = (event: DragEvent) => {
event.dataTransfer.clearData();
event.dataTransfer.setData("text/html", dom.innerHTML);
event.dataTransfer.setData("text/plain", text);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
event.dataTransfer.setDragImage(activeNode?.el as any, 0, 0);
currEditorView.dragging = {
@ -289,6 +291,7 @@ const getDraggableItem = ({
editor: Editor;
view: EditorView;
dom: HTMLElement;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
event?: any;
depth?: number;
}): DraggableItemType | boolean | undefined => {

View File

@ -16,9 +16,11 @@ declare module "@/tiptap" {
export interface FormatBrushStore {
formatBrush: boolean;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
formatBrushMarks: any[];
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const formatBrush = Extension.create<any, FormatBrushStore>({
name: "formatBrush",

View File

@ -30,6 +30,7 @@ class GapCursorSelection extends Selection {
return other instanceof GapCursorSelection && other.head == this.head;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
toJSON(): any {
return { type: "node-gap-cursor", pos: this.head };
}
@ -38,6 +39,7 @@ class GapCursorSelection extends Selection {
return this.start;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
static fromJSON(doc: PMNode, json: any): GapCursorSelection {
if (typeof json.pos != "number") {
throw new RangeError("Invalid input for GapCursorSelection.fromJSON");
@ -144,6 +146,7 @@ class GapCursorSelection extends Selection {
}
GapCursorSelection.prototype.visible = false;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(GapCursorSelection as any).findFrom = GapCursorSelection.findGapCursorFrom;
Selection.jsonID("node-gap-cursor", GapCursorSelection);

View File

@ -282,6 +282,7 @@ export function arrow(axis: "vert" | "horiz", dir: number): Command {
export const arrowGapCursor = (
dir: number,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
dirStr: any,
state: EditorState,
view?: EditorView

View File

@ -282,7 +282,7 @@ const Blockquote = TiptapHeading.extend<ExtensionOptions & HeadingOptions>({
return [
new Plugin({
key: new PluginKey("generate-heading-id"),
appendTransaction: (transactions, oldState, newState) => {
appendTransaction: (transactions, _oldState, newState) => {
const isChangeHeading = transactions.some((transaction) => {
const composition = this.editor.view.composing;
if (beforeComposition !== undefined && !composition) {

View File

@ -24,6 +24,7 @@ type IndentOptions = {
minIndentLevel: number;
maxIndentLevel: number;
defaultIndentLevel: number;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
HTMLAttributes: Record<string, any>;
firstLineIndent: boolean;
};

View File

@ -45,6 +45,7 @@ class RangeSelection extends Selection {
return new RangeBookmark(this.anchor, this.head);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
toJSON(): any {
return { type: "range", anchor: this.anchor, head: this.head };
}
@ -125,6 +126,7 @@ class RangeSelection extends Selection {
return new RangeSelection(doc.resolve(anchor), doc.resolve(head));
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
static fromJSON(doc: Node, json: any) {
if (typeof json.anchor != "number" || typeof json.head != "number") {
throw new RangeError("Invalid input for RangeSelection.fromJSON");

View File

@ -58,6 +58,7 @@ const findPreviousSearchResult = () => {
props.editor.commands.findPrevious();
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const updateSearchReplace = (value: any) => {
const { editor, pluginKey } = props;
if (!editor || !pluginKey) {

View File

@ -345,7 +345,7 @@ export class SearchAndReplacePluginState {
*/
getFullText(doc: PMNode): TextNodesWithPosition[] {
const textNodesWithPosition: TextNodesWithPosition[] = [];
doc.descendants((node, pos, parent, index) => {
doc.descendants((node, pos, _parent, index) => {
if (node.isText) {
textNodesWithPosition.push({
text: `${node.text}`,

View File

@ -42,6 +42,7 @@ declare module "@/tiptap" {
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const instance = h<any>(SearchAndReplaceVue);
function isShowSearch() {
const searchAndReplaceInstance = instance.component;
@ -95,6 +96,7 @@ const SearchAndReplace = Extension.create<ExtensionOptions>({
dispatch,
}: {
state: EditorState;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
dispatch: ((args?: any) => any) | undefined;
}) => {
const searchAndReplaceState =
@ -130,6 +132,7 @@ const SearchAndReplace = Extension.create<ExtensionOptions>({
dispatch,
}: {
state: EditorState;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
dispatch: ((args?: any) => any) | undefined;
}) => {
const searchAndReplaceState =
@ -161,6 +164,7 @@ const SearchAndReplace = Extension.create<ExtensionOptions>({
dispatch,
}: {
state: EditorState;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
dispatch: ((args?: any) => any) | undefined;
}) => {
if (dispatch) {
@ -187,6 +191,7 @@ const SearchAndReplace = Extension.create<ExtensionOptions>({
dispatch,
}: {
state: EditorState;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
dispatch: ((args?: any) => any) | undefined;
}) => {
if (dispatch) {
@ -212,6 +217,7 @@ const SearchAndReplace = Extension.create<ExtensionOptions>({
dispatch,
}: {
state: EditorState;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
dispatch: ((args?: any) => any) | undefined;
}) => {
const searchAndReplaceState =
@ -240,6 +246,7 @@ const SearchAndReplace = Extension.create<ExtensionOptions>({
dispatch,
}: {
state: EditorState;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
dispatch: ((args?: any) => any) | undefined;
}) => {
const searchAndReplaceState =

View File

@ -54,6 +54,7 @@ function updateColumns(
table: HTMLElement,
cellMinWidth: number,
overrideCol?: number,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
overrideValue?: any
) {
let totalWidth = 0;

View File

@ -19,6 +19,7 @@ import {
} from "./util";
export interface TableCellOptions {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
HTMLAttributes: Record<string, any>;
}

View File

@ -13,6 +13,7 @@ import MdiPlus from "~icons/mdi/plus";
import { getCellsInRow, isColumnSelected, selectColumn } from "./util";
export interface TableCellOptions {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
HTMLAttributes: Record<string, any>;
}

View File

@ -150,6 +150,7 @@ export const findTable = (selection: Selection) => {
| undefined;
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const isRectSelected = (rect: any) => (selection: CellSelection) => {
const map = TableMap.get(selection.$anchorCell.node(-1));
const start = selection.$anchorCell.start(-1);
@ -170,10 +171,12 @@ export const isRectSelected = (rect: any) => (selection: CellSelection) => {
return true;
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const isCellSelection = (selection: any) => {
return selection instanceof CellSelection;
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const isColumnSelected = (columnIndex: number) => (selection: any) => {
if (isCellSelection(selection)) {
const map = TableMap.get(selection.$anchorCell.node(-1));
@ -199,6 +202,7 @@ export const isColumnSelected = (columnIndex: number) => (selection: any) => {
return false;
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const isRowSelected = (rowIndex: number) => (selection: any) => {
if (isCellSelection(selection)) {
const map = TableMap.get(selection.$anchorCell.node(-1));
@ -223,6 +227,7 @@ export const isRowSelected = (rowIndex: number) => (selection: any) => {
return false;
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const isTableSelected = (selection: any) => {
if (isCellSelection(selection)) {
const map = TableMap.get(selection.$anchorCell.node(-1));

View File

@ -6,6 +6,7 @@ import { Extension } from "@/tiptap/vue-3";
* @param {Array | object} args.types possible types
* @param {object} args.node node to check
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function nodeEqualsType({ types, node }: { types: any; node: any }) {
return (
(Array.isArray(types) && types.includes(node.type)) || node.type === types

View File

@ -3,9 +3,9 @@
// see https://github.com/ueberdosis/tiptap/pull/5160
const ATTR_WHITESPACE =
/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g; // eslint-disable-line no-control-regex
/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g;
const IS_ALLOWED_URI =
/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i; // eslint-disable-line no-useless-escape
/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i;
export function isAllowedUri(uri: string | undefined) {
return !uri || uri.replace(ATTR_WHITESPACE, "").match(IS_ALLOWED_URI);

View File

@ -1,3 +0,0 @@
module.exports = {
extends: ["../../.eslintrc.cjs"],
};

View File

@ -30,7 +30,6 @@
"scripts": {
"build": "tsdown",
"dev": "tsdown --watch",
"lint": "eslint ./src --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts",
"prettier": "prettier --write './src/**/*.{vue,js,jsx,ts,tsx,css,scss,json,yml,yaml,html}'",
"typecheck": "tsc --noEmit -p tsconfig.app.json --composite false"
},

View File

@ -1,2 +0,0 @@
dist/*
node_modules/*

View File

@ -1,3 +0,0 @@
module.exports = {
extends: ["../../.eslintrc.cjs"],
};

File diff suppressed because it is too large Load Diff

View File

@ -34,7 +34,7 @@ onMounted(async () => {
isLoading.value = true;
try {
await loadImage();
} catch (e) {
} catch (_) {
error.value = true;
} finally {
isLoading.value = false;

View File

@ -89,7 +89,7 @@ const uppy = computed(() => {
return new Error(message);
}
}
} catch (e) {
} catch (_) {
const responseBody = response as XMLHttpRequest;
const { status, statusText } = responseBody;
const defaultMessage = [status, statusText].join(": ");

View File

@ -32,7 +32,7 @@ onMounted(async () => {
isLoading.value = true;
try {
await loadVideo();
} catch (e) {
} catch (_) {
error.value = true;
} finally {
isLoading.value = false;

View File

@ -93,7 +93,9 @@ export function useContentCache(
(c: ContentCache) => c.name === ""
);
}
index > -1 && content_caches.value.splice(index, 1);
if (index > -1) {
content_caches.value.splice(index, 1);
}
};
return {

View File

@ -59,20 +59,23 @@ function listFeature(node: FormKitNode) {
const fns = node.context.fns;
fns.createShift = (index: number, offset: number) => () => {
const value = node._value as unknown[];
value.splice(index + offset, 0, value.splice(index, 1)[0]),
node.input(value, false);
value.splice(index + offset, 0, value.splice(index, 1)[0]);
node.input(value, false);
};
fns.createInsert = (index: number) => () => {
const value = node._value as unknown[];
value.splice(index + 1, 0, fn(node)), node.input(value, false);
value.splice(index + 1, 0, fn(node));
node.input(value, false);
};
fns.createAppend = () => () => {
const value = node._value as unknown[];
value.push(fn(node)), node.input(value, false);
value.push(fn(node));
node.input(value, false);
};
fns.createRemover = (index: number) => () => {
const value = node._value as unknown[];
value.splice(index, 1), node.input(value, false);
value.splice(index, 1);
node.input(value, false);
};
}
}

View File

@ -9,7 +9,7 @@ export const repeats = function (node: FormKitNode) {
type FnType = (index: number) => object;
function createValue(num: number, fn: FnType) {
return new Array(num).fill("").map((value, index) => fn(index));
return new Array(num).fill("").map((_, index) => fn(index));
}
function repeaterFeature(node: FormKitNode) {
@ -50,20 +50,23 @@ function repeaterFeature(node: FormKitNode) {
const fns = node.context.fns;
fns.createShift = (index: number, offset: number) => () => {
const value = node._value as unknown[];
value.splice(index + offset, 0, value.splice(index, 1)[0]),
node.input(value, false);
value.splice(index + offset, 0, value.splice(index, 1)[0]);
node.input(value, false);
};
fns.createInsert = (index: number) => () => {
const value = node._value as unknown[];
value.splice(index + 1, 0, {}), node.input(value, false);
value.splice(index + 1, 0, {});
node.input(value, false);
};
fns.createAppend = () => () => {
const value = node._value as unknown[];
value.push({}), node.input(value, false);
value.push({});
node.input(value, false);
};
fns.createRemover = (index: number) => () => {
const value = node._value as unknown[];
value.splice(index, 1), node.input(value, false);
value.splice(index, 1);
node.input(value, false);
};
}
}

View File

@ -34,7 +34,9 @@ export function useUserFetch(options?: {
};
onMounted(() => {
fetchOnMounted && handleFetchUsers();
if (fetchOnMounted) {
handleFetchUsers();
}
});
return {

View File

@ -4,7 +4,7 @@ import type { Router } from "vue-router";
const whiteList = ["ResetPassword"];
export function setupAuthCheckGuard(router: Router) {
router.beforeEach((to, from, next) => {
router.beforeEach((to, _from, next) => {
if (whiteList.includes(to.name as string)) {
next();
return;

View File

@ -3,7 +3,7 @@ import { hasPermission } from "@/utils/permission";
import type { Router } from "vue-router";
export function setupPermissionGuard(router: Router) {
router.beforeEach((to, from, next) => {
router.beforeEach((to, _from, next) => {
const roleStore = useRoleStore();
const { uiPermissions } = roleStore.permissions;
const { meta } = to;