mirror of
https://github.com/langgenius/dify.git
synced 2026-03-20 13:03:03 -04:00
docs(web): update dev guide (#33815)
This commit is contained in:
5
.github/workflows/autofix.yml
vendored
5
.github/workflows/autofix.yml
vendored
@@ -94,11 +94,6 @@ jobs:
|
||||
find . -name "*.py" -type f -exec sed -i.bak -E 's/"([^"]+)" \| None/Optional["\1"]/g; s/'"'"'([^'"'"']+)'"'"' \| None/Optional['"'"'\1'"'"']/g' {} \;
|
||||
find . -name "*.py.bak" -type f -delete
|
||||
|
||||
# mdformat breaks YAML front matter in markdown files. Add --exclude for directories containing YAML front matter.
|
||||
- name: mdformat
|
||||
run: |
|
||||
uvx --python 3.13 mdformat . --exclude ".agents/skills/**"
|
||||
|
||||
- name: Setup web environment
|
||||
if: steps.web-changes.outputs.any_changed == 'true'
|
||||
uses: ./.github/actions/setup-web
|
||||
|
||||
@@ -6,19 +6,23 @@ NEXT_PUBLIC_EDITION=SELF_HOSTED
|
||||
NEXT_PUBLIC_BASE_PATH=
|
||||
# The base URL of console application, refers to the Console base URL of WEB service if console domain is
|
||||
# different from api or web app domain.
|
||||
# example: http://cloud.dify.ai/console/api
|
||||
# example: https://cloud.dify.ai/console/api
|
||||
NEXT_PUBLIC_API_PREFIX=http://localhost:5001/console/api
|
||||
# The URL for Web APP, refers to the Web App base URL of WEB service if web app domain is different from
|
||||
# console or api domain.
|
||||
# example: http://udify.app/api
|
||||
# example: https://udify.app/api
|
||||
NEXT_PUBLIC_PUBLIC_API_PREFIX=http://localhost:5001/api
|
||||
# Dev-only Hono proxy targets. The frontend keeps requesting http://localhost:5001 directly.
|
||||
# When the frontend and backend run on different subdomains, set NEXT_PUBLIC_COOKIE_DOMAIN=1.
|
||||
NEXT_PUBLIC_COOKIE_DOMAIN=
|
||||
|
||||
# Dev-only Hono proxy targets.
|
||||
# The frontend keeps requesting http://localhost:5001 directly,
|
||||
# the proxy server will forward the request to the target server,
|
||||
# so that you don't need to run a separate backend server and use online API in development.
|
||||
HONO_PROXY_HOST=127.0.0.1
|
||||
HONO_PROXY_PORT=5001
|
||||
HONO_CONSOLE_API_PROXY_TARGET=
|
||||
HONO_PUBLIC_API_PROXY_TARGET=
|
||||
# When the frontend and backend run on different subdomains, set NEXT_PUBLIC_COOKIE_DOMAIN=1.
|
||||
NEXT_PUBLIC_COOKIE_DOMAIN=
|
||||
|
||||
# The API PREFIX for MARKETPLACE
|
||||
NEXT_PUBLIC_MARKETPLACE_API_PREFIX=https://marketplace.dify.ai/api/v1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Dify Frontend
|
||||
|
||||
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
|
||||
This is a [Next.js] project, but you can dev with [vinext].
|
||||
|
||||
## Getting Started
|
||||
|
||||
@@ -8,8 +8,11 @@ This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next
|
||||
|
||||
Before starting the web frontend service, please make sure the following environment is ready.
|
||||
|
||||
- [Node.js](https://nodejs.org)
|
||||
- [pnpm](https://pnpm.io)
|
||||
- [Node.js]
|
||||
- [pnpm]
|
||||
|
||||
You can also use [Vite+] with the corresponding `vp` commands.
|
||||
For example, use `vp install` instead of `pnpm install` and `vp test` instead of `pnpm run test`.
|
||||
|
||||
> [!TIP]
|
||||
> It is recommended to install and enable Corepack to manage package manager versions automatically:
|
||||
@@ -19,7 +22,7 @@ Before starting the web frontend service, please make sure the following environ
|
||||
> corepack enable
|
||||
> ```
|
||||
>
|
||||
> Learn more: [Corepack](https://github.com/nodejs/corepack#readme)
|
||||
> Learn more: [Corepack]
|
||||
|
||||
First, install the dependencies:
|
||||
|
||||
@@ -27,31 +30,14 @@ First, install the dependencies:
|
||||
pnpm install
|
||||
```
|
||||
|
||||
Then, configure the environment variables. Create a file named `.env.local` in the current directory and copy the contents from `.env.example`. Modify the values of these environment variables according to your requirements:
|
||||
Then, configure the environment variables.
|
||||
Create a file named `.env.local` in the current directory and copy the contents from `.env.example`.
|
||||
Modify the values of these environment variables according to your requirements:
|
||||
|
||||
```bash
|
||||
cp .env.example .env.local
|
||||
```
|
||||
|
||||
```txt
|
||||
# For production release, change this to PRODUCTION
|
||||
NEXT_PUBLIC_DEPLOY_ENV=DEVELOPMENT
|
||||
# The deployment edition, SELF_HOSTED
|
||||
NEXT_PUBLIC_EDITION=SELF_HOSTED
|
||||
# The base URL of console application, refers to the Console base URL of WEB service if console domain is
|
||||
# different from api or web app domain.
|
||||
# example: http://cloud.dify.ai/console/api
|
||||
NEXT_PUBLIC_API_PREFIX=http://localhost:5001/console/api
|
||||
NEXT_PUBLIC_COOKIE_DOMAIN=
|
||||
# The URL for Web APP, refers to the Web App base URL of WEB service if web app domain is different from
|
||||
# console or api domain.
|
||||
# example: http://udify.app/api
|
||||
NEXT_PUBLIC_PUBLIC_API_PREFIX=http://localhost:5001/api
|
||||
|
||||
# SENTRY
|
||||
NEXT_PUBLIC_SENTRY_DSN=
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> 1. When the frontend and backend run on different subdomains, set NEXT_PUBLIC_COOKIE_DOMAIN=1. The frontend and backend must be under the same top-level domain in order to share authentication cookies.
|
||||
@@ -61,11 +47,16 @@ Finally, run the development server:
|
||||
|
||||
```bash
|
||||
pnpm run dev
|
||||
# or if you are using vinext which provides a better development experience
|
||||
pnpm run dev:vinext
|
||||
# (optional) start the dev proxy server so that you can use online API in development
|
||||
pnpm run dev:proxy
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
Open <http://localhost:3000> with your browser to see the result.
|
||||
|
||||
You can start editing the file under folder `app`. The page auto-updates as you edit the file.
|
||||
You can start editing the file under folder `app`.
|
||||
The page auto-updates as you edit the file.
|
||||
|
||||
## Deploy
|
||||
|
||||
@@ -91,7 +82,7 @@ pnpm run start --port=3001 --host=0.0.0.0
|
||||
|
||||
## Storybook
|
||||
|
||||
This project uses [Storybook](https://storybook.js.org/) for UI component development.
|
||||
This project uses [Storybook] for UI component development.
|
||||
|
||||
To start the storybook server, run:
|
||||
|
||||
@@ -99,19 +90,24 @@ To start the storybook server, run:
|
||||
pnpm storybook
|
||||
```
|
||||
|
||||
Open [http://localhost:6006](http://localhost:6006) with your browser to see the result.
|
||||
Open <http://localhost:6006> with your browser to see the result.
|
||||
|
||||
## Lint Code
|
||||
|
||||
If your IDE is VSCode, rename `web/.vscode/settings.example.json` to `web/.vscode/settings.json` for lint code setting.
|
||||
|
||||
Then follow the [Lint Documentation](./docs/lint.md) to lint the code.
|
||||
Then follow the [Lint Documentation] to lint the code.
|
||||
|
||||
## Test
|
||||
|
||||
We use [Vitest](https://vitest.dev/) and [React Testing Library](https://testing-library.com/docs/react-testing-library/intro/) for Unit Testing.
|
||||
We use [Vitest] and [React Testing Library] for Unit Testing.
|
||||
|
||||
**📖 Complete Testing Guide**: See [web/testing/testing.md](./testing/testing.md) for detailed testing specifications, best practices, and examples.
|
||||
**📖 Complete Testing Guide**: See [web/docs/test.md] for detailed testing specifications, best practices, and examples.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> As we are using Vite+, the `vitest` command is not available.
|
||||
> Please make sure to run tests with `vp` commands.
|
||||
> For example, use `npx vp test` instead of `npx vitest`.
|
||||
|
||||
Run test:
|
||||
|
||||
@@ -119,12 +115,17 @@ Run test:
|
||||
pnpm test
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Our test is not fully stable yet, and we are actively working on improving it.
|
||||
> If you encounter test failures only in CI but not locally, please feel free to ignore them and report the issue to us.
|
||||
> You can try to re-run the test in CI, and it may pass successfully.
|
||||
|
||||
### Example Code
|
||||
|
||||
If you are not familiar with writing tests, refer to:
|
||||
|
||||
- [classnames.spec.ts](./utils/classnames.spec.ts) - Utility function test example
|
||||
- [index.spec.tsx](./app/components/base/button/index.spec.tsx) - Component test example
|
||||
- [classnames.spec.ts] - Utility function test example
|
||||
- [index.spec.tsx] - Component test example
|
||||
|
||||
### Analyze Component Complexity
|
||||
|
||||
@@ -134,7 +135,7 @@ Before writing tests, use the script to analyze component complexity:
|
||||
pnpm analyze-component app/components/your-component/index.tsx
|
||||
```
|
||||
|
||||
This will help you determine the testing strategy. See [web/testing/testing.md](./testing/testing.md) for details.
|
||||
This will help you determine the testing strategy. See [web/testing/testing.md] for details.
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -142,4 +143,19 @@ Visit <https://docs.dify.ai> to view the full documentation.
|
||||
|
||||
## Community
|
||||
|
||||
The Dify community can be found on [Discord community](https://discord.gg/5AEfbxcd9k), where you can ask questions, voice ideas, and share your projects.
|
||||
The Dify community can be found on [Discord community], where you can ask questions, voice ideas, and share your projects.
|
||||
|
||||
[Corepack]: https://github.com/nodejs/corepack#readme
|
||||
[Discord community]: https://discord.gg/5AEfbxcd9k
|
||||
[Lint Documentation]: ./docs/lint.md
|
||||
[Next.js]: https://nextjs.org
|
||||
[Node.js]: https://nodejs.org
|
||||
[React Testing Library]: https://testing-library.com/docs/react-testing-library/intro
|
||||
[Storybook]: https://storybook.js.org
|
||||
[Vite+]: https://viteplus.dev
|
||||
[Vitest]: https://vitest.dev
|
||||
[classnames.spec.ts]: ./utils/classnames.spec.ts
|
||||
[index.spec.tsx]: ./app/components/base/button/index.spec.tsx
|
||||
[pnpm]: https://pnpm.io
|
||||
[vinext]: https://github.com/cloudflare/vinext
|
||||
[web/docs/test.md]: ./docs/test.md
|
||||
|
||||
@@ -12,25 +12,44 @@ We use ESLint and Typescript to maintain code quality and consistency across the
|
||||
pnpm eslint [options] file.js [file.js] [dir]
|
||||
```
|
||||
|
||||
**`--cache`**: Caches lint results for faster subsequent runs. Keep this enabled by default; only disable when you encounter unexpected lint results.
|
||||
**`--cache`**: Caches lint results for faster subsequent runs.
|
||||
Keep this enabled by default; only disable when you encounter unexpected lint results.
|
||||
|
||||
**`--concurrency`**: Enables multi-threaded linting. Use `--concurrency=auto` or experiment with specific numbers to find the optimal setting for your machine. Keep this enabled when linting multiple files.
|
||||
**`--concurrency`**: Enables multi-threaded linting.
|
||||
Use `--concurrency=auto` or experiment with specific numbers to find the optimal setting for your machine.
|
||||
Keep this enabled when linting multiple files.
|
||||
|
||||
- [ESLint multi-thread linting blog post](https://eslint.org/blog/2025/08/multithread-linting/)
|
||||
- [ESLint multi-thread linting blog post]
|
||||
|
||||
**`--fix`**: Automatically fixes auto-fixable rule violations. Always review the diff before committing to ensure no unintended changes.
|
||||
**`--fix`**: Automatically fixes auto-fixable rule violations.
|
||||
Keep this enabled so that you do not have to care about auto-fixable errors (e.g., formatting issues) and can focus on more important errors.
|
||||
Always review the diff before committing to ensure no unintended changes.
|
||||
|
||||
**`--quiet`**: Suppresses warnings and only shows errors. Useful when you want to reduce noise from existing issues.
|
||||
**`--quiet`**: Suppresses warnings and only shows errors.
|
||||
Useful when you want to reduce noise from existing warnings.
|
||||
|
||||
**`--suppress-all`**: Temporarily suppresses error-level violations and records them, allowing CI to pass. Treat this as an escape hatch—fix these errors when time permits.
|
||||
**`--suppress-all`**: Temporarily suppresses error-level violations and records them, allowing CI to pass.
|
||||
Treat this as an escape hatch—fix these errors when time permits.
|
||||
|
||||
**`--prune-suppressions`**: Removes outdated suppressions after you've fixed the underlying errors.
|
||||
|
||||
- [ESLint bulk suppressions blog post](https://eslint.org/blog/2025/04/introducing-bulk-suppressions/)
|
||||
- [ESLint bulk suppressions blog post]
|
||||
|
||||
### The Auto-Fix Workflow and Suppression Strategy
|
||||
|
||||
To streamline your development process, we recommend configuring your editor to automatically fix lint errors on save.
|
||||
As a fallback, any remaining autofixable errors will be corrected automatically when you commit.
|
||||
To prevent workflow disruptions, these commit hooks are intentionally bypassed when you are merging branches, rebasing, or cherry-picking.
|
||||
|
||||
Additionally, we currently track many existing legacy errors in eslint-suppressions.json.
|
||||
You do not need to spend time manually pruning these suppressions (we already append `--pass-on-unpruned-suppressions` in the commit hook);
|
||||
once you open a Pull Request, the CI pipeline will automatically handle the cleanup for you.
|
||||
|
||||
### Type-Aware Linting
|
||||
|
||||
Some ESLint rules require type information, such as [no-leaked-conditional-rendering](https://www.eslint-react.xyz/docs/rules/no-leaked-conditional-rendering). However, [typed linting via typescript-eslint](https://typescript-eslint.io/getting-started/typed-linting) is too slow for practical use, so we use [TSSLint](https://github.com/johnsoncodehk/tsslint) instead.
|
||||
Some ESLint rules require type information, such as [no-leaked-conditional-rendering].
|
||||
However, [typed linting via typescript-eslint] is too slow for practical use.
|
||||
So we use [TSSLint] instead.
|
||||
|
||||
```sh
|
||||
pnpm lint:tss
|
||||
@@ -43,7 +62,7 @@ This command lints the entire project and is intended for final verification bef
|
||||
If a new rule causes many existing code errors or automatic fixes generate too many diffs, do not use the `--fix` option for automatic fixes.
|
||||
You can introduce the rule first, then use the `--suppress-all` option to temporarily suppress these errors, and gradually fix them in subsequent changes.
|
||||
|
||||
For overlay migration policy and cleanup phases, see [Overlay Migration Guide](./overlay-migration.md).
|
||||
For overlay migration policy and cleanup phases, see [Overlay Migration Guide].
|
||||
|
||||
## Type Check
|
||||
|
||||
@@ -55,4 +74,12 @@ However, it can be useful to run the TypeScript 7 command-line (tsgo) to type ch
|
||||
pnpm type-check:tsgo
|
||||
```
|
||||
|
||||
Prefer using `tsgo` for type checking as it is significantly faster than the standard TypeScript compiler. Only fall back to `pnpm type-check` (which uses `tsc`) if you encounter unexpected results.
|
||||
Prefer using `tsgo` for type checking as it is significantly faster than the standard TypeScript compiler.
|
||||
Only fall back to `pnpm type-check` (which uses `tsc`) if you encounter unexpected results.
|
||||
|
||||
[ESLint bulk suppressions blog post]: https://eslint.org/blog/2025/04/introducing-bulk-suppressions
|
||||
[ESLint multi-thread linting blog post]: https://eslint.org/blog/2025/08/multithread-linting
|
||||
[Overlay Migration Guide]: ./overlay-migration.md
|
||||
[TSSLint]: https://github.com/johnsoncodehk/tsslint
|
||||
[no-leaked-conditional-rendering]: https://www.eslint-react.xyz/docs/rules/no-leaked-conditional-rendering
|
||||
[typed linting via typescript-eslint]: https://typescript-eslint.io/getting-started/typed-linting
|
||||
|
||||
@@ -23,7 +23,7 @@ This document tracks the migration away from legacy overlay APIs.
|
||||
- `@/app/components/base/ui/alert-dialog`
|
||||
- `@/app/components/base/ui/select`
|
||||
- `@/app/components/base/ui/toast`
|
||||
- Tracking issue: https://github.com/langgenius/dify/issues/32767
|
||||
- Tracking issue: <https://github.com/langgenius/dify/issues/32767>
|
||||
|
||||
## ESLint policy
|
||||
|
||||
@@ -72,14 +72,14 @@ All new overlay primitives in `base/ui/` share a single z-index value:
|
||||
During the migration period, legacy and new overlays coexist. Legacy overlays
|
||||
portal to `document.body` with explicit z-index values:
|
||||
|
||||
| Layer | z-index | Components |
|
||||
|-------|---------|------------|
|
||||
| Legacy Drawer | `z-[30]` | `base/drawer` |
|
||||
| Legacy Modal | `z-[60]` | `base/modal` (default) |
|
||||
| Legacy PortalToFollowElem callers | up to `z-[1001]` | various business components |
|
||||
| **New UI primitives** | **`z-[1002]`** | `base/ui/*` (Popover, Dialog, Tooltip, etc.) |
|
||||
| Legacy Modal (highPriority) | `z-[1100]` | `base/modal` (`highPriority={true}`) |
|
||||
| Toast (legacy + new) | `z-[1101]` | `base/toast`, `base/ui/toast` |
|
||||
| Layer | z-index | Components |
|
||||
| --------------------------------- | ---------------- | -------------------------------------------- |
|
||||
| Legacy Drawer | `z-[30]` | `base/drawer` |
|
||||
| Legacy Modal | `z-[60]` | `base/modal` (default) |
|
||||
| Legacy PortalToFollowElem callers | up to `z-[1001]` | various business components |
|
||||
| **New UI primitives** | **`z-[1002]`** | `base/ui/*` (Popover, Dialog, Tooltip, etc.) |
|
||||
| Legacy Modal (highPriority) | `z-[1100]` | `base/modal` (`highPriority={true}`) |
|
||||
| Toast (legacy + new) | `z-[1101]` | `base/toast`, `base/ui/toast` |
|
||||
|
||||
`z-[1002]` sits above all common legacy overlays, so new primitives always
|
||||
render on top without needing per-call-site z-index hacks. Among themselves,
|
||||
|
||||
@@ -119,13 +119,11 @@ When assigned to test a **directory/path** (not just a single file), follow thes
|
||||
Choose based on directory complexity:
|
||||
|
||||
1. **Single spec file (Integration approach)** - Preferred for related components
|
||||
|
||||
- Minimize mocking - use real project components
|
||||
- Test actual integration between components
|
||||
- Only mock: API calls, complex context providers, third-party libs
|
||||
|
||||
1. **Multiple spec files (Unit approach)** - For complex directories
|
||||
|
||||
- One spec file per component/hook/utility
|
||||
- More isolated testing
|
||||
- Useful when components are independent
|
||||
@@ -139,7 +137,7 @@ When using a single spec file:
|
||||
- ❌ **DO NOT mock** base components (`@/app/components/base/*`)
|
||||
- ❌ **DO NOT mock** sibling/child components in the same directory
|
||||
|
||||
> See [Example Structure](#example-structure) for correct import/mock patterns.
|
||||
> See [Example Structure] for correct import/mock patterns.
|
||||
|
||||
## Testing Components with Dedicated Dependencies
|
||||
|
||||
@@ -185,8 +183,8 @@ Treat component state as part of the public behavior: confirm the initial render
|
||||
- ✅ When creating lightweight provider stubs, mirror the real default values and surface helper builders (for example `createMockWorkflowContext`).
|
||||
- ✅ Reset shared stores (React context, Zustand, TanStack Query cache) between tests to avoid leaking state. Prefer helper factory functions over module-level singletons in specs.
|
||||
- ✅ For hooks that read from context, use `renderHook` with a custom wrapper that supplies required providers.
|
||||
- ✅ **Use factory functions for mock data**: Import actual types and create factory functions with complete defaults (see [Test Data Builders](#9-test-data-builders-anti-hardcoding) section).
|
||||
- ✅ If it's need to mock some common context provider used across many components (for example, `ProviderContext`), put it in __mocks__/context(for example, `__mocks__/context/provider-context`). To dynamically control the mock behavior (for example, toggling plan type), use module-level variables to track state and change them(for example, `context/provider-context-mock.spec.tsx`).
|
||||
- ✅ **Use factory functions for mock data**: Import actual types and create factory functions with complete defaults (see [Test Data Builders] section).
|
||||
- ✅ If it's need to mock some common context provider used across many components (for example, `ProviderContext`), put it in **mocks**/context(for example, `__mocks__/context/provider-context`). To dynamically control the mock behavior (for example, toggling plan type), use module-level variables to track state and change them(for example, `context/provider-context-mock.spec.tsx`).
|
||||
- ✅ Use factory functions to create mock data with TypeScript types. This ensures type safety and makes tests more maintainable.
|
||||
|
||||
**Rules**:
|
||||
@@ -363,7 +361,6 @@ describe('ComponentName', () => {
|
||||
1. **i18n**: Uses global mock in `web/vitest.setup.ts` (auto-loaded by Vitest setup)
|
||||
|
||||
The global mock provides:
|
||||
|
||||
- `useTranslation` - returns translation keys with namespace prefix
|
||||
- `Trans` component - renders i18nKey and components
|
||||
- `useMixedTranslation` (from `@/app/components/plugins/marketplace/hooks`)
|
||||
@@ -533,16 +530,25 @@ const element = await screen.findByText('Async Content')
|
||||
|
||||
Test examples in the project:
|
||||
|
||||
- [classnames.spec.ts](../utils/classnames.spec.ts) - Utility function tests
|
||||
- [index.spec.tsx](../app/components/base/button/index.spec.tsx) - Component tests
|
||||
- [classnames.spec.ts] - Utility function tests
|
||||
- [index.spec.tsx] - Component tests
|
||||
|
||||
## Resources
|
||||
|
||||
- [Vitest Documentation](https://vitest.dev/guide/)
|
||||
- [React Testing Library Documentation](https://testing-library.com/docs/react-testing-library/intro/)
|
||||
- [Testing Library Best Practices](https://kentcdodds.com/blog/common-mistakes-with-react-testing-library)
|
||||
- [Vitest Mocking Guide](https://vitest.dev/guide/mocking.html)
|
||||
- [Vitest Documentation]
|
||||
- [React Testing Library Documentation]
|
||||
- [Testing Library Best Practices]
|
||||
- [Vitest Mocking Guide]
|
||||
|
||||
______________________________________________________________________
|
||||
---
|
||||
|
||||
**Remember**: Writing tests is not just about coverage, but ensuring code quality and maintainability. Good tests should be clear, concise, and meaningful.
|
||||
|
||||
[Example Structure]: #example-structure
|
||||
[React Testing Library Documentation]: https://testing-library.com/docs/react-testing-library/intro
|
||||
[Test Data Builders]: #9-test-data-builders-anti-hardcoding
|
||||
[Testing Library Best Practices]: https://kentcdodds.com/blog/common-mistakes-with-react-testing-library
|
||||
[Vitest Documentation]: https://vitest.dev/guide
|
||||
[Vitest Mocking Guide]: https://vitest.dev/guide/mocking.html
|
||||
[classnames.spec.ts]: ../utils/classnames.spec.ts
|
||||
[index.spec.tsx]: ../app/components/base/button/index.spec.tsx
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
// @ts-check
|
||||
import antfu, { GLOB_TESTS, GLOB_TS, GLOB_TSX, isInEditorEnv, isInGitHooksOrLintStaged } from '@antfu/eslint-config'
|
||||
|
||||
import antfu, { GLOB_MARKDOWN, GLOB_TESTS, GLOB_TS, GLOB_TSX, isInEditorEnv, isInGitHooksOrLintStaged } from '@antfu/eslint-config'
|
||||
import pluginQuery from '@tanstack/eslint-plugin-query'
|
||||
import md from 'eslint-markdown'
|
||||
import tailwindcss from 'eslint-plugin-better-tailwindcss'
|
||||
import hyoban from 'eslint-plugin-hyoban'
|
||||
import markdownPreferences from 'eslint-plugin-markdown-preferences'
|
||||
import sonar from 'eslint-plugin-sonarjs'
|
||||
import storybook from 'eslint-plugin-storybook'
|
||||
import {
|
||||
@@ -56,6 +59,26 @@ export default antfu(
|
||||
},
|
||||
e18e: false,
|
||||
},
|
||||
markdownPreferences.configs.standard,
|
||||
{
|
||||
files: [GLOB_MARKDOWN],
|
||||
plugins: { md },
|
||||
rules: {
|
||||
'md/no-url-trailing-slash': 'error',
|
||||
'markdown-preferences/prefer-link-reference-definitions': [
|
||||
'error',
|
||||
{
|
||||
minLinks: 1,
|
||||
},
|
||||
],
|
||||
'markdown-preferences/ordered-list-marker-sequence': [
|
||||
'error',
|
||||
{ increment: 'never' },
|
||||
],
|
||||
'markdown-preferences/definitions-last': 'error',
|
||||
'markdown-preferences/sort-definitions': 'error',
|
||||
},
|
||||
},
|
||||
{
|
||||
rules: {
|
||||
'node/prefer-global/process': 'off',
|
||||
|
||||
@@ -41,7 +41,7 @@ cd web/i18n
|
||||
cp -r en-US id-ID
|
||||
```
|
||||
|
||||
2. Modify the translation `.json` files in the new folder. Keep keys flat (for example, `dialog.title`).
|
||||
1. Modify the translation `.json` files in the new folder. Keep keys flat (for example, `dialog.title`).
|
||||
|
||||
1. Add the new language to the `languages.ts` file.
|
||||
|
||||
@@ -143,10 +143,10 @@ export const languages = [
|
||||
]
|
||||
```
|
||||
|
||||
4. Don't forget to mark the supported field as `true` if the language is supported.
|
||||
1. Don't forget to mark the supported field as `true` if the language is supported.
|
||||
|
||||
1. Sometimes you might need to do some changes in the server side. Please change this file as well. 👇
|
||||
https://github.com/langgenius/dify/blob/61e4bbabaf2758354db4073cbea09fdd21a5bec1/api/constants/languages.py#L5
|
||||
<https://github.com/langgenius/dify/blob/61e4bbabaf2758354db4073cbea09fdd21a5bec1/api/constants/languages.py#L5>
|
||||
|
||||
> Note: `I18nText` type is automatically derived from `LanguagesSupported`, so you don't need to manually add types.
|
||||
|
||||
|
||||
@@ -216,8 +216,10 @@
|
||||
"autoprefixer": "10.4.27",
|
||||
"code-inspector-plugin": "1.4.4",
|
||||
"eslint": "10.0.3",
|
||||
"eslint-markdown": "0.6.0",
|
||||
"eslint-plugin-better-tailwindcss": "4.3.2",
|
||||
"eslint-plugin-hyoban": "0.14.1",
|
||||
"eslint-plugin-markdown-preferences": "0.40.3",
|
||||
"eslint-plugin-react-hooks": "7.0.1",
|
||||
"eslint-plugin-react-refresh": "0.5.2",
|
||||
"eslint-plugin-sonarjs": "4.0.2",
|
||||
|
||||
52
web/pnpm-lock.yaml
generated
52
web/pnpm-lock.yaml
generated
@@ -530,12 +530,18 @@ importers:
|
||||
eslint:
|
||||
specifier: 10.0.3
|
||||
version: 10.0.3(jiti@1.21.7)
|
||||
eslint-markdown:
|
||||
specifier: 0.6.0
|
||||
version: 0.6.0(eslint@10.0.3(jiti@1.21.7))
|
||||
eslint-plugin-better-tailwindcss:
|
||||
specifier: 4.3.2
|
||||
version: 4.3.2(eslint@10.0.3(jiti@1.21.7))(oxlint@1.55.0(oxlint-tsgolint@0.17.0))(tailwindcss@3.4.19(tsx@4.21.0)(yaml@2.8.2))(typescript@5.9.3)
|
||||
eslint-plugin-hyoban:
|
||||
specifier: 0.14.1
|
||||
version: 0.14.1(eslint@10.0.3(jiti@1.21.7))
|
||||
eslint-plugin-markdown-preferences:
|
||||
specifier: 0.40.3
|
||||
version: 0.40.3(@eslint/markdown@7.5.1)(eslint@10.0.3(jiti@1.21.7))
|
||||
eslint-plugin-react-hooks:
|
||||
specifier: 7.0.1
|
||||
version: 7.0.1(eslint@10.0.3(jiti@1.21.7))
|
||||
@@ -4763,6 +4769,15 @@ packages:
|
||||
'@eslint/json':
|
||||
optional: true
|
||||
|
||||
eslint-markdown@0.6.0:
|
||||
resolution: {integrity: sha512-NrgfiNto5IJrW1F/Akf2hJYoJTCbXoClOUvtUMDgoqmQNH0VRihNvFh+MFay4E0HV2eozfgxsLSGxnndtRJA8w==}
|
||||
engines: {node: ^20.19.0 || ^22.13.0 || >=24.0.0}
|
||||
peerDependencies:
|
||||
eslint: ^9.31.0 || ^10.0.0-rc.0
|
||||
peerDependenciesMeta:
|
||||
eslint:
|
||||
optional: true
|
||||
|
||||
eslint-merge-processors@2.0.0:
|
||||
resolution: {integrity: sha512-sUuhSf3IrJdGooquEUB5TNpGNpBoQccbnaLHsb1XkBLUPPqCNivCpY05ZcpCOiV9uHwO2yxXEWVczVclzMxYlA==}
|
||||
peerDependencies:
|
||||
@@ -4828,6 +4843,13 @@ packages:
|
||||
peerDependencies:
|
||||
eslint: '>=9.38.0'
|
||||
|
||||
eslint-plugin-markdown-preferences@0.40.3:
|
||||
resolution: {integrity: sha512-R3CCAEFwnnYXukTdtvdsamGjbTgVs9UZKqMKhNeWNXzFtOP1Frc89bgbd56lJUN7ASaxgvzc5fUpKvDCOTtDpg==}
|
||||
engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
|
||||
peerDependencies:
|
||||
'@eslint/markdown': ^7.4.0
|
||||
eslint: '>=9.0.0'
|
||||
|
||||
eslint-plugin-n@17.24.0:
|
||||
resolution: {integrity: sha512-/gC7/KAYmfNnPNOb3eu8vw+TdVnV0zhdQwexsw6FLXbhzroVj20vRn2qL8lDWDGnAQ2J8DhdfvXxX9EoxvERvw==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
@@ -12142,6 +12164,16 @@ snapshots:
|
||||
esquery: 1.7.0
|
||||
jsonc-eslint-parser: 3.1.0
|
||||
|
||||
eslint-markdown@0.6.0(eslint@10.0.3(jiti@1.21.7)):
|
||||
dependencies:
|
||||
'@eslint/markdown': 7.5.1
|
||||
micromark-util-normalize-identifier: 2.0.1
|
||||
parse5: 8.0.0
|
||||
optionalDependencies:
|
||||
eslint: 10.0.3(jiti@1.21.7)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-merge-processors@2.0.0(eslint@10.0.3(jiti@1.21.7)):
|
||||
dependencies:
|
||||
eslint: 10.0.3(jiti@1.21.7)
|
||||
@@ -12233,6 +12265,26 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- '@eslint/json'
|
||||
|
||||
eslint-plugin-markdown-preferences@0.40.3(@eslint/markdown@7.5.1)(eslint@10.0.3(jiti@1.21.7)):
|
||||
dependencies:
|
||||
'@eslint/markdown': 7.5.1
|
||||
diff-sequences: 29.6.3
|
||||
emoji-regex-xs: 2.0.1
|
||||
eslint: 10.0.3(jiti@1.21.7)
|
||||
mdast-util-from-markdown: 2.0.3
|
||||
mdast-util-frontmatter: 2.0.1
|
||||
mdast-util-gfm: 3.1.0
|
||||
mdast-util-math: 3.0.0
|
||||
micromark-extension-frontmatter: 2.0.0
|
||||
micromark-extension-gfm: 3.0.0
|
||||
micromark-extension-math: 3.1.0
|
||||
micromark-factory-space: 2.0.1
|
||||
micromark-util-character: 2.1.1
|
||||
micromark-util-symbol: 2.0.1
|
||||
string-width: 8.2.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-plugin-n@17.24.0(eslint@10.0.3(jiti@1.21.7))(typescript@5.9.3):
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.9.1(eslint@10.0.3(jiti@1.21.7))
|
||||
|
||||
Reference in New Issue
Block a user