mirror of
https://github.com/AppFlowy-IO/AppFlowy-Web.git
synced 2025-11-29 02:38:00 +08:00
feat: add rule for eslint import & autofix (#116)
* feat: add rule for eslint import & autofix * feat: autofix unused import * feat: autofix unused import * test: seems secret is not working
This commit is contained in:
@@ -3,4 +3,5 @@ dist/
|
||||
.eslintrc.cjs
|
||||
tsconfig.json
|
||||
vite.config.ts
|
||||
vite-env.d.ts
|
||||
coverage/
|
||||
@@ -5,7 +5,12 @@ module.exports = {
|
||||
es6: true,
|
||||
node: true,
|
||||
},
|
||||
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:import/recommended',
|
||||
'plugin:import/typescript'
|
||||
],
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
project: 'tsconfig.json',
|
||||
@@ -13,7 +18,15 @@ module.exports = {
|
||||
tsconfigRootDir: __dirname,
|
||||
extraFileExtensions: ['.json'],
|
||||
},
|
||||
plugins: ['@typescript-eslint', 'react-hooks'],
|
||||
plugins: ['@typescript-eslint', 'react-hooks', 'import', 'unused-imports'],
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
typescript: {
|
||||
alwaysTryTypes: true,
|
||||
project: 'tsconfig.json',
|
||||
},
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'react-hooks/rules-of-hooks': 'error',
|
||||
'react-hooks/exhaustive-deps': 'error',
|
||||
@@ -34,7 +47,8 @@ module.exports = {
|
||||
eqeqeq: ['error', 'always'],
|
||||
'no-cond-assign': 'error',
|
||||
'no-duplicate-case': 'error',
|
||||
'no-duplicate-imports': 'error',
|
||||
// replaced by import/no-duplicates
|
||||
'no-duplicate-imports': 'off',
|
||||
'no-empty': [
|
||||
'error',
|
||||
{
|
||||
@@ -66,8 +80,66 @@ module.exports = {
|
||||
{ blankLine: 'any', prev: 'import', next: 'import' },
|
||||
{ blankLine: 'always', prev: 'block-like', next: '*' },
|
||||
{ blankLine: 'always', prev: 'block', next: '*' },
|
||||
|
||||
],
|
||||
'import/no-unresolved': ['error', {
|
||||
ignore: ['\\.svg$', 'bun']
|
||||
}],
|
||||
'import/named': 'warn',
|
||||
'import/namespace': 'warn',
|
||||
'import/default': 'warn',
|
||||
'import/export': 'warn',
|
||||
'import/no-duplicates': 'error',
|
||||
// Detect whether there are modules that are exported but not used.
|
||||
'import/no-unused-modules': 'warn',
|
||||
|
||||
// unused-imports should be error level so eslint can auto fix it
|
||||
'unused-imports/no-unused-imports': 'error',
|
||||
'unused-imports/no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
vars: 'all',
|
||||
varsIgnorePattern: '^_',
|
||||
args: 'after-used',
|
||||
argsIgnorePattern: '^_'
|
||||
}
|
||||
],
|
||||
'@typescript-eslint/no-unused-vars': ['error', {
|
||||
vars: 'all',
|
||||
varsIgnorePattern: '^_',
|
||||
args: 'after-used',
|
||||
argsIgnorePattern: '^_'
|
||||
}],
|
||||
|
||||
'import/order': ['warn', {
|
||||
'groups': [
|
||||
'builtin',
|
||||
'external',
|
||||
'internal',
|
||||
'parent',
|
||||
'sibling',
|
||||
'index',
|
||||
'object',
|
||||
'type'
|
||||
],
|
||||
'newlines-between': 'always',
|
||||
'alphabetize': {
|
||||
'order': 'asc',
|
||||
'caseInsensitive': true
|
||||
},
|
||||
'pathGroups': [
|
||||
{
|
||||
'pattern': '@/**',
|
||||
'group': 'internal',
|
||||
'position': 'after'
|
||||
},
|
||||
{
|
||||
'pattern': 'src/**',
|
||||
'group': 'internal',
|
||||
'position': 'after'
|
||||
}
|
||||
],
|
||||
'pathGroupsExcludedImportTypes': ['builtin']
|
||||
}]
|
||||
},
|
||||
ignorePatterns: ['src/**/*.test.ts', '**/__tests__/**/*.json', 'package.json', '__mocks__/*.ts'],
|
||||
};
|
||||
|
||||
3
.github/workflows/web_coverage.yaml
vendored
3
.github/workflows/web_coverage.yaml
vendored
@@ -44,7 +44,6 @@ jobs:
|
||||
with:
|
||||
component: true
|
||||
build: pnpm run build
|
||||
start: pnpm run start
|
||||
browser: chrome
|
||||
env:
|
||||
COVERAGE: "true"
|
||||
@@ -58,7 +57,7 @@ jobs:
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v2
|
||||
with:
|
||||
token: ${{ secrets.WEB_CODE_COV }}
|
||||
token: cf9245e0-e136-4e21-b0ee-35755fa0c493
|
||||
files: coverage/jest/lcov.info, coverage/cypress/lcov.info
|
||||
flags: appflowy_web
|
||||
name: codecov-umbrella
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import pino from 'pino';
|
||||
import { type CheerioAPI, load } from 'cheerio';
|
||||
import path from 'path';
|
||||
|
||||
// @ts-expect-error no bun
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
import { fetch } from 'bun';
|
||||
import { type CheerioAPI, load } from 'cheerio';
|
||||
import pino from 'pino';
|
||||
|
||||
const distDir = path.join(__dirname, 'dist');
|
||||
const indexPath = path.join(distDir, 'index.html');
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"build": "vite build",
|
||||
"type-check": "tsc --noEmit --project tsconfig.web.json",
|
||||
"type-check:watch": "tsc --build --watch",
|
||||
"lint": "pnpm type-check && eslint --ext .js,.ts,.tsx . --ignore-path .eslintignore.web",
|
||||
"lint": "pnpm type-check && eslint --quiet --ext .js,.ts,.tsx . --ignore-path .eslintignore.web",
|
||||
"start": "vite preview --port 3000",
|
||||
"css:variables": "node scripts/generateTailwindColors.cjs",
|
||||
"analyze": "cross-env ANALYZE_MODE=true vite build",
|
||||
@@ -181,9 +181,12 @@
|
||||
"cypress-image-snapshot": "^4.0.1",
|
||||
"cypress-real-events": "^1.13.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-import-resolver-typescript": "^3.6.1",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-react": "^7.32.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.6",
|
||||
"eslint-plugin-unused-imports": "^4.1.4",
|
||||
"istanbul-lib-coverage": "^3.2.2",
|
||||
"jest-environment-jsdom": "^29.6.2",
|
||||
"jest-node-exports-resolver": "^1.1.6",
|
||||
|
||||
980
pnpm-lock.yaml
generated
980
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
import { YDatabaseCell, YjsDatabaseKey } from '@/application/types';
|
||||
import { FieldType } from '@/application/database-yjs/database.type';
|
||||
import { YArray } from 'yjs/dist/src/types/YArray';
|
||||
import * as Y from 'yjs';
|
||||
import { Cell, CheckboxCell, DateTimeCell, FileMediaCell, FileMediaCellData } from './cell.type';
|
||||
|
||||
export function parseYDatabaseCommonCellToCell(cell: YDatabaseCell): Cell {
|
||||
@@ -43,7 +43,7 @@ export function parseYDatabaseDateTimeCellToCell (cell: YDatabaseCell): DateTime
|
||||
}
|
||||
|
||||
export function parseYDatabaseFileMediaCellToCell(cell: YDatabaseCell): FileMediaCell {
|
||||
const data = cell.get(YjsDatabaseKey.data) as YArray<string>;
|
||||
const data = cell.get(YjsDatabaseKey.data) as Y.Array<string>;
|
||||
const dataJson = data.toJSON().map((item: string) => JSON.parse(item)) as FileMediaCellData;
|
||||
|
||||
return {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { FieldId, RowId } from '@/application/types';
|
||||
import { DateFormat, TimeFormat } from '@/application/database-yjs/index';
|
||||
import { FieldType } from '@/application/database-yjs/database.type';
|
||||
import React from 'react';
|
||||
import { YArray } from 'yjs/dist/src/types/YArray';
|
||||
import * as Y from 'yjs';
|
||||
|
||||
export interface Cell {
|
||||
createdAt: number;
|
||||
@@ -97,7 +97,7 @@ export interface ChecklistCell extends Cell {
|
||||
|
||||
export interface RelationCell extends Cell {
|
||||
fieldType: FieldType.Relation;
|
||||
data: YArray<unknown>;
|
||||
data: Y.Array<unknown>;
|
||||
}
|
||||
|
||||
export type RelationCellData = RowId[];
|
||||
|
||||
@@ -46,7 +46,7 @@ import dayjs from 'dayjs';
|
||||
import { omit } from 'lodash-es';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { notify } from '@/components/_shared/notify';
|
||||
import { RepeatedChatMessage } from '@appflowyinc/ai-chat/dist/types';
|
||||
import { RepeatedChatMessage } from '@appflowyinc/ai-chat';
|
||||
|
||||
export * from './gotrue';
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ import {
|
||||
YjsEditorKey,
|
||||
} from '@/application/types';
|
||||
import { applyYDoc } from '@/application/ydoc/apply';
|
||||
import { RepeatedChatMessage } from '@appflowyinc/ai-chat/dist/types';
|
||||
import { RepeatedChatMessage } from '@appflowyinc/ai-chat';
|
||||
import { nanoid } from 'nanoid';
|
||||
import * as Y from 'yjs';
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ import {
|
||||
UploadTemplatePayload,
|
||||
} from '@/application/template.type';
|
||||
import { AxiosInstance } from 'axios';
|
||||
import { RepeatedChatMessage } from '@appflowyinc/ai-chat/dist/types';
|
||||
import { RepeatedChatMessage } from '@appflowyinc/ai-chat';
|
||||
|
||||
export type AFService =
|
||||
PublishService
|
||||
|
||||
@@ -5,7 +5,7 @@ import { YBlock, YjsEditorKey } from '@/application/types';
|
||||
import isEqual from 'lodash-es/isEqual';
|
||||
import { Editor, Element, NodeEntry } from 'slate';
|
||||
import { YEvent, YMapEvent, YTextEvent } from 'yjs';
|
||||
import { YText } from 'yjs/dist/src/types/YText';
|
||||
import * as Y from 'yjs';
|
||||
import { dataStringTOJson, getBlock, getChildrenArray, getPageId, getText } from '@/application/slate-yjs/utils/yjs';
|
||||
import { findSlateEntryByBlockId } from '@/application/slate-yjs/utils/editor';
|
||||
|
||||
@@ -65,7 +65,7 @@ function applyUpdateBlockYEvent(editor: YjsEditor, blockId: string, event: YMapE
|
||||
function applyTextYEvent(editor: YjsEditor, textId: string, event: YTextEvent) {
|
||||
const { target } = event;
|
||||
|
||||
const yText = target as YText;
|
||||
const yText = target as Y.Text;
|
||||
const delta = yText.toDelta();
|
||||
const slateDelta = delta.flatMap(deltaInsertToSlateNode);
|
||||
const [entry] = editor.nodes({
|
||||
|
||||
@@ -9,13 +9,15 @@ import { notify } from '@/components/_shared/notify';
|
||||
import { insertDataAfterBlock } from '@/components/ai-chat/utils';
|
||||
import { useEditorContext } from '@/components/editor/EditorContext';
|
||||
import { getScrollParent } from '@/components/global-comment/utils';
|
||||
|
||||
import { AIAssistantProvider, ContextPlaceholder, WriterRequest } from '@appflowyinc/ai-chat';
|
||||
import { EditorData } from '@appflowyinc/editor';
|
||||
import { Portal } from '@mui/material';
|
||||
import React, { useCallback, useEffect, useMemo } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { ErrorBoundary } from 'react-error-boundary';
|
||||
import { Element, NodeEntry, Range, Text, Transforms } from 'slate';
|
||||
import { ReactEditor, useSlate } from 'slate-react';
|
||||
|
||||
import BlockPopover from './components/block-popover';
|
||||
import Panels from './components/panels';
|
||||
import Toolbars from './components/toolbar';
|
||||
@@ -143,9 +145,9 @@ function EditorOverlay({
|
||||
}
|
||||
}, [removeDecorate, editor]);
|
||||
|
||||
const [container, setContainer] = React.useState<HTMLDivElement | null>(null);
|
||||
const [scrollerContainer, setScrollerContainer] = React.useState<HTMLDivElement | null>(null);
|
||||
const [absoluteHeight, setAbsoluteHeight] = React.useState(0);
|
||||
const [container, setContainer] = useState<HTMLDivElement | null>(null);
|
||||
const [scrollerContainer, setScrollerContainer] = useState<HTMLDivElement | null>(null);
|
||||
const [absoluteHeight, setAbsoluteHeight] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
if (endBlock) {
|
||||
|
||||
@@ -99,6 +99,7 @@ export default defineConfig({
|
||||
server: {
|
||||
port: process.env.PORT ? parseInt(process.env.PORT) : 3000,
|
||||
strictPort: true,
|
||||
host: '0.0.0.0',
|
||||
watch: {
|
||||
ignored: ['node_modules'],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user