From ec8ff89dc1040c83cccc75596b409746579222dd Mon Sep 17 00:00:00 2001 From: Stephen Zhou Date: Fri, 20 Mar 2026 17:23:17 +0800 Subject: [PATCH] docs(web): update dev guide (#33815) --- .github/workflows/autofix.yml | 5 -- web/.env.example | 14 ++++-- web/README.md | 86 +++++++++++++++++++++-------------- web/docs/lint.md | 47 +++++++++++++++---- web/docs/overlay-migration.md | 18 ++++---- web/docs/test.md | 32 +++++++------ web/eslint.config.mjs | 25 +++++++++- web/i18n-config/README.md | 6 +-- web/package.json | 2 + web/pnpm-lock.yaml | 52 +++++++++++++++++++++ 10 files changed, 206 insertions(+), 81 deletions(-) diff --git a/.github/workflows/autofix.yml b/.github/workflows/autofix.yml index 8947ae4030..be6186980e 100644 --- a/.github/workflows/autofix.yml +++ b/.github/workflows/autofix.yml @@ -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 diff --git a/web/.env.example b/web/.env.example index ed06ebe2c9..079c3bdeef 100644 --- a/web/.env.example +++ b/web/.env.example @@ -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 diff --git a/web/README.md b/web/README.md index 1e57e7c6a9..14ca856875 100644 --- a/web/README.md +++ b/web/README.md @@ -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 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 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 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 diff --git a/web/docs/lint.md b/web/docs/lint.md index 1105d4af08..0203964621 100644 --- a/web/docs/lint.md +++ b/web/docs/lint.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 diff --git a/web/docs/overlay-migration.md b/web/docs/overlay-migration.md index 23f08fd043..253d4c5bcd 100644 --- a/web/docs/overlay-migration.md +++ b/web/docs/overlay-migration.md @@ -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: ## 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, diff --git a/web/docs/test.md b/web/docs/test.md index 1f82f59234..2facdbb29f 100644 --- a/web/docs/test.md +++ b/web/docs/test.md @@ -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 diff --git a/web/eslint.config.mjs b/web/eslint.config.mjs index ee26de85e9..55008d9ec4 100644 --- a/web/eslint.config.mjs +++ b/web/eslint.config.mjs @@ -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', diff --git a/web/i18n-config/README.md b/web/i18n-config/README.md index 2bfa1ef024..e173947c0d 100644 --- a/web/i18n-config/README.md +++ b/web/i18n-config/README.md @@ -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 + > Note: `I18nText` type is automatically derived from `LanguagesSupported`, so you don't need to manually add types. diff --git a/web/package.json b/web/package.json index 5c08965ed0..e499d39fef 100644 --- a/web/package.json +++ b/web/package.json @@ -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", diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index 5c4ccfc5c8..3132e98a25 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -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))