chore: use react-grab to replace code-inspector-plugin (#33078)

This commit is contained in:
Stephen Zhou 2026-03-06 14:54:24 +08:00 committed by GitHub
parent e74cda6535
commit f05f0be55f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 250 additions and 427 deletions

View File

@ -0,0 +1,17 @@
import Script from 'next/script'
import { IS_DEV } from '@/config'
export function ReactGrabLoader() {
if (!IS_DEV)
return null
return (
<>
<Script
src="//unpkg.com/react-grab/dist/index.global.js"
crossOrigin="anonymous"
strategy="beforeInteractive"
/>
</>
)
}

View File

@ -11,6 +11,7 @@ import { cn } from '@/utils/classnames'
import { ToastProvider } from './components/base/toast'
import { TooltipProvider } from './components/base/ui/tooltip'
import BrowserInitializer from './components/browser-initializer'
import { ReactGrabLoader } from './components/devtools/react-grab/loader'
import { ReactScanLoader } from './components/devtools/react-scan/loader'
import { I18nServerProvider } from './components/provider/i18n-server'
import SentryInitializer from './components/sentry-initializer'
@ -56,6 +57,7 @@ const LocaleLayout = async ({
<meta name="msapplication-TileColor" content="#1C64F2" />
<meta name="msapplication-config" content="/browserconfig.xml" />
<ReactGrabLoader />
<ReactScanLoader />
</head>
<body

View File

@ -5,8 +5,8 @@ import tailwindcss from 'eslint-plugin-better-tailwindcss'
import hyoban from 'eslint-plugin-hyoban'
import sonar from 'eslint-plugin-sonarjs'
import storybook from 'eslint-plugin-storybook'
import dify from './eslint-rules/index.js'
import { OVERLAY_MIGRATION_LEGACY_BASE_FILES } from './eslint.constants.mjs'
import dify from './plugins/eslint/index.js'
// Enable Tailwind CSS IntelliSense mode for ESLint runs
// See: tailwind-css-plugin.ts

View File

@ -1,21 +1,9 @@
import type { NextConfig } from 'next'
import createMDX from '@next/mdx'
import { codeInspectorPlugin } from 'code-inspector-plugin'
import { env } from './env'
const isDev = process.env.NODE_ENV === 'development'
const withMDX = createMDX({
extension: /\.mdx?$/,
options: {
// If you use remark-gfm, you'll need to use next.config.mjs
// as the package is ESM only
// https://github.com/remarkjs/remark-gfm#install
remarkPlugins: [],
rehypePlugins: [],
// If you use `MDXProvider`, uncomment the following line.
// providerImportSource: "@mdx-js/react",
},
})
const withMDX = createMDX()
// the default url to prevent parse url error when running jest
const hasSetWebPrefix = env.NEXT_PUBLIC_WEB_PREFIX
@ -26,11 +14,6 @@ const remoteImageURLs = ([hasSetWebPrefix ? new URL(`${env.NEXT_PUBLIC_WEB_PREFI
const nextConfig: NextConfig = {
basePath: env.NEXT_PUBLIC_BASE_PATH,
transpilePackages: ['@t3-oss/env-core', '@t3-oss/env-nextjs', 'echarts', 'zrender'],
turbopack: {
rules: codeInspectorPlugin({
bundler: 'turbopack',
}),
},
productionBrowserSourceMaps: false, // enable browser source map generation during the production build
// Configure pageExtensions to include md and mdx
pageExtensions: ['ts', 'tsx', 'js', 'jsx', 'md', 'mdx'],
@ -48,7 +31,6 @@ const nextConfig: NextConfig = {
// https://nextjs.org/docs/api-reference/next.config.js/ignoring-typescript-errors
ignoreBuildErrors: true,
},
reactStrictMode: true,
async redirects() {
return [
{

View File

@ -217,7 +217,6 @@
"@vitejs/plugin-rsc": "0.5.21",
"@vitest/coverage-v8": "4.0.18",
"autoprefixer": "10.4.21",
"code-inspector-plugin": "1.3.6",
"cross-env": "10.1.0",
"eslint": "10.0.2",
"eslint-plugin-better-tailwindcss": "https://pkg.pr.new/hyoban/eslint-plugin-better-tailwindcss@a520d15",
@ -235,7 +234,6 @@
"nock": "14.0.10",
"postcss": "8.5.6",
"postcss-js": "5.0.3",
"react-scan": "0.5.3",
"react-server-dom-webpack": "19.2.4",
"sass": "1.93.2",
"storybook": "10.2.13",

View File

@ -0,0 +1,80 @@
import type { Plugin } from 'vite'
import fs from 'node:fs'
import { injectClientSnippet, normalizeViteModuleId } from './utils'
type CustomI18nHmrPluginOptions = {
injectTarget: string
}
export const customI18nHmrPlugin = ({ injectTarget }: CustomI18nHmrPluginOptions): Plugin => {
const i18nHmrClientMarker = 'custom-i18n-hmr-client'
const i18nHmrClientSnippet = `/* ${i18nHmrClientMarker} */
if (import.meta.hot) {
const getI18nUpdateTarget = (file) => {
const match = file.match(/[/\\\\]i18n[/\\\\]([^/\\\\]+)[/\\\\]([^/\\\\]+)\\.json$/)
if (!match)
return null
const [, locale, namespaceFile] = match
return { locale, namespaceFile }
}
import.meta.hot.on('i18n-update', async ({ file, content }) => {
const target = getI18nUpdateTarget(file)
if (!target)
return
const [{ getI18n }, { camelCase }] = await Promise.all([
import('react-i18next'),
import('es-toolkit/string'),
])
const i18n = getI18n()
if (!i18n)
return
if (target.locale !== i18n.language)
return
let resources
try {
resources = JSON.parse(content)
}
catch {
return
}
const namespace = camelCase(target.namespaceFile)
i18n.addResourceBundle(target.locale, namespace, resources, true, true)
i18n.emit('languageChanged', i18n.language)
})
}
`
return {
name: 'custom-i18n-hmr',
apply: 'serve',
handleHotUpdate({ file, server }) {
if (file.endsWith('.json') && file.includes('/i18n/')) {
server.ws.send({
type: 'custom',
event: 'i18n-update',
data: {
file,
content: fs.readFileSync(file, 'utf-8'),
},
})
return []
}
},
transform(code, id) {
const cleanId = normalizeViteModuleId(id)
if (cleanId !== injectTarget)
return null
const nextCode = injectClientSnippet(code, i18nHmrClientMarker, i18nHmrClientSnippet)
if (nextCode === code)
return null
return { code: nextCode, map: null }
},
}
}

View File

@ -0,0 +1,92 @@
import type { Plugin } from 'vite'
import { injectClientSnippet, normalizeViteModuleId } from './utils'
type ReactGrabOpenFilePluginOptions = {
injectTarget: string
projectRoot: string
}
export const reactGrabOpenFilePlugin = ({
injectTarget,
projectRoot,
}: ReactGrabOpenFilePluginOptions): Plugin => {
const reactGrabOpenFileClientMarker = 'react-grab-open-file-client'
const reactGrabOpenFileClientSnippet = `/* ${reactGrabOpenFileClientMarker} */
if (typeof window !== 'undefined') {
const projectRoot = ${JSON.stringify(projectRoot)};
const pluginName = 'dify-vite-open-file';
const rootRelativeSourcePathPattern = /^\\/(?!@|node_modules)(?:.+)\\.(?:[cm]?[jt]sx?|mdx?)$/;
const normalizeProjectRoot = (input) => {
return input.endsWith('/') ? input.slice(0, -1) : input;
};
const resolveFilePath = (filePath) => {
if (filePath.startsWith('/@fs/')) {
return filePath.slice('/@fs'.length);
}
if (!rootRelativeSourcePathPattern.test(filePath)) {
return filePath;
}
const normalizedProjectRoot = normalizeProjectRoot(projectRoot);
if (filePath.startsWith(normalizedProjectRoot)) {
return filePath;
}
return \`\${normalizedProjectRoot}\${filePath}\`;
};
const registerPlugin = () => {
if (window.__DIFY_REACT_GRAB_OPEN_FILE_PLUGIN_REGISTERED__) {
return;
}
const reactGrab = window.__REACT_GRAB__;
if (!reactGrab) {
return;
}
reactGrab.registerPlugin({
name: pluginName,
hooks: {
onOpenFile(filePath, lineNumber) {
const params = new URLSearchParams({
file: resolveFilePath(filePath),
column: '1',
});
if (lineNumber) {
params.set('line', String(lineNumber));
}
void fetch(\`/__open-in-editor?\${params.toString()}\`);
return true;
},
},
});
window.__DIFY_REACT_GRAB_OPEN_FILE_PLUGIN_REGISTERED__ = true;
};
registerPlugin();
window.addEventListener('react-grab:init', registerPlugin);
}
`
return {
name: 'react-grab-open-file',
apply: 'serve',
transform(code, id) {
const cleanId = normalizeViteModuleId(id)
if (cleanId !== injectTarget)
return null
const nextCode = injectClientSnippet(code, reactGrabOpenFileClientMarker, reactGrabOpenFileClientSnippet)
if (nextCode === code)
return null
return { code: nextCode, map: null }
},
}
}

20
web/plugins/vite/utils.ts Normal file
View File

@ -0,0 +1,20 @@
export const normalizeViteModuleId = (id: string): string => {
const withoutQuery = id.split('?', 1)[0]
if (withoutQuery.startsWith('/@fs/'))
return withoutQuery.slice('/@fs'.length)
return withoutQuery
}
export const injectClientSnippet = (code: string, marker: string, snippet: string): string => {
if (code.includes(marker))
return code
const useClientMatch = code.match(/(['"])use client\1;?\s*\n/)
if (!useClientMatch)
return `${snippet}\n${code}`
const insertAt = (useClientMatch.index ?? 0) + useClientMatch[0].length
return `${code.slice(0, insertAt)}\n${snippet}\n${code.slice(insertAt)}`
}

View File

@ -215,7 +215,7 @@ importers:
version: 11.1.0
jotai:
specifier: 2.16.1
version: 2.16.1(@babel/core@7.29.0)(@babel/template@7.28.6)(@types/react@19.2.9)(react@19.2.4)
version: 2.16.1(@babel/core@7.28.6)(@babel/template@7.28.6)(@types/react@19.2.9)(react@19.2.4)
js-audio-recorder:
specifier: 1.0.7
version: 1.0.7
@ -254,13 +254,13 @@ importers:
version: 1.0.0
next:
specifier: 16.1.5
version: 16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2)
version: 16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2)
next-themes:
specifier: 0.4.6
version: 0.4.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
nuqs:
specifier: 2.8.6
version: 2.8.6(next@16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react@19.2.4)
version: 2.8.6(next@16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react@19.2.4)
pinyin-pro:
specifier: 3.27.0
version: 3.27.0
@ -420,7 +420,7 @@ importers:
version: 10.2.13(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))
'@storybook/nextjs-vite':
specifier: 10.2.13
version: 10.2.13(@babel/core@7.29.0)(esbuild@0.27.2)(next@16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.56.0)(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3))
version: 10.2.13(@babel/core@7.28.6)(esbuild@0.27.2)(next@16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.56.0)(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3))
'@storybook/react':
specifier: 10.2.13
version: 10.2.13(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)
@ -517,9 +517,6 @@ importers:
autoprefixer:
specifier: 10.4.21
version: 10.4.21(postcss@8.5.6)
code-inspector-plugin:
specifier: 1.3.6
version: 1.3.6
cross-env:
specifier: 10.1.0
version: 10.1.0
@ -571,9 +568,6 @@ importers:
postcss-js:
specifier: 5.0.3
version: 5.0.3(postcss@8.5.6)
react-scan:
specifier: 0.5.3
version: 0.5.3(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.56.0)
react-server-dom-webpack:
specifier: 19.2.4
version: 19.2.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3))
@ -597,7 +591,7 @@ importers:
version: 3.19.3
vinext:
specifier: https://pkg.pr.new/hyoban/vinext@556a6d6
version: https://pkg.pr.new/hyoban/vinext@556a6d6(next@16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3))
version: https://pkg.pr.new/hyoban/vinext@556a6d6(next@16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3))
vite:
specifier: 8.0.0-beta.16
version: 8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
@ -955,24 +949,6 @@ packages:
'@clack/prompts@1.0.1':
resolution: {integrity: sha512-/42G73JkuYdyWZ6m8d/CJtBrGl1Hegyc7Fy78m5Ob+jF85TOUmLR5XLce/U3LxYAw0kJ8CT5aI99RIvPHcGp/Q==}
'@code-inspector/core@1.3.6':
resolution: {integrity: sha512-bSxf/PWDPY6rv9EFf0mJvTnLnz3927PPrpX6BmQcRKQab+Ez95yRqrVZY8IcBUpaqA/k3etA5rZ1qkN0V4ERtw==}
'@code-inspector/esbuild@1.3.6':
resolution: {integrity: sha512-s35dseBXI2yqfX6ZK29Ix941jaE/4KPlZZeMk6B5vDahj75FDUfVxQ7ORy4cX2hyz8CmlOycsY/au5mIvFpAFg==}
'@code-inspector/mako@1.3.6':
resolution: {integrity: sha512-FJvuTElOi3TUCWTIaYTFYk2iTUD6MlO51SC8SYfwmelhuvnOvTMa2TkylInX16OGb4f7sGNLRj2r+7NNx/gqpw==}
'@code-inspector/turbopack@1.3.6':
resolution: {integrity: sha512-pfXgvZCn4/brpTvqy8E0HTe6V/ksVKEPQo697Nt5k22kBnlEM61UT3rI2Art+fDDEMPQTxVOFpdbwCKSLwMnmQ==}
'@code-inspector/vite@1.3.6':
resolution: {integrity: sha512-vXYvzGc0S1NR4p3BeD1Xx2170OnyecZD0GtebLlTiHw/cetzlrBHVpbkIwIEzzzpTYYshwwDt8ZbuvdjmqhHgw==}
'@code-inspector/webpack@1.3.6':
resolution: {integrity: sha512-bi/+vsym9d6NXQQ++Phk74VLMiVoGKjgPHr445j/D43URG8AN8yYa+gRDBEDcZx4B128dihrVMxEO8+OgWGjTw==}
'@csstools/color-helpers@5.1.0':
resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==}
engines: {node: '>=18'}
@ -2188,11 +2164,6 @@ packages:
'@preact/signals-core@1.12.2':
resolution: {integrity: sha512-5Yf8h1Ke3SMHr15xl630KtwPTW4sYDFkkxS0vQ8UiQLWwZQnrF9IKaVG1mN5VcJz52EcWs2acsc/Npjha/7ysA==}
'@preact/signals@1.3.2':
resolution: {integrity: sha512-naxcJgUJ6BTOROJ7C3QML7KvwKwCXQJYTc5L/b0eEsdYgPB6SxwoQ1vDGcS0Q7GVjAenVq/tXrybVdFShHYZWg==}
peerDependencies:
preact: 10.x
'@radix-ui/primitive@1.1.3':
resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==}
@ -3295,9 +3266,6 @@ packages:
'@types/negotiator@0.6.4':
resolution: {integrity: sha512-elf6BsTq+AkyNsb2h5cGNst2Mc7dPliVoAPm1fXglC/BM3f2pFA40BaSSv3E5lyHteEawVKLP+8TwiY1DMNb3A==}
'@types/node@20.19.30':
resolution: {integrity: sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==}
'@types/node@24.10.12':
resolution: {integrity: sha512-68e+T28EbdmLSTkPgs3+UacC6rzmqrcWFPQs1C8mwJhI/r5Uxr0yEuQotczNRROd1gq30NGxee+fo0rSIxpyAw==}
@ -3315,11 +3283,6 @@ packages:
peerDependencies:
'@types/react': ^19.2.0
'@types/react-reconciler@0.28.9':
resolution: {integrity: sha512-HHM3nxyUZ3zAylX8ZEyrDNd2XZOnQ0D5XfunJF5FLQnZbHHYq4UWvW1QfelQNXv1ICNkwYhfxjwfnqivYB6bFg==}
peerDependencies:
'@types/react': '*'
'@types/react-slider@1.3.6':
resolution: {integrity: sha512-RS8XN5O159YQ6tu3tGZIQz1/9StMLTg/FCIPxwqh2gwVixJnlfIodtVx+fpXVMZHe7A58lAX1Q4XTgAGOQaCQg==}
@ -3818,9 +3781,6 @@ packages:
resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==}
hasBin: true
async@3.2.6:
resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==}
autoprefixer@10.4.21:
resolution: {integrity: sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==}
engines: {node: ^10 || ^12 || >=14}
@ -3862,11 +3822,6 @@ packages:
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
engines: {node: '>=8'}
bippy@0.5.30:
resolution: {integrity: sha512-8CFmJAHD3gmTLDOCDHuWhjm1nxHSFZdlGoWtak9r53Uxn36ynOjxBLyxXHh/7h/XiKLyPvfdXa0gXWcD9o9lLQ==}
peerDependencies:
react: '>=17.0.1'
birecord@0.1.1:
resolution: {integrity: sha512-VUpsf/qykW0heRlC8LooCq28Kxn3mAqKohhDG/49rrsQ1dT1CXyj/pgXS+5BSRzFTR/3DyIBOqQOrGyZOh71Aw==}
@ -3949,10 +3904,6 @@ packages:
resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==}
engines: {node: '>=18'}
chalk@4.1.1:
resolution: {integrity: sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==}
engines: {node: '>=10'}
chalk@4.1.2:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
@ -4077,9 +4028,6 @@ packages:
react: ^18 || ^19 || ^19.0.0-rc
react-dom: ^18 || ^19 || ^19.0.0-rc
code-inspector-plugin@1.3.6:
resolution: {integrity: sha512-ddTg8embDqLZxKEdSNOm+/0YnVVgWKr10+Bu2qFqQDObj/3twGh0Z23TIz+5/URxfRhTPbp2sUSpWlw78piJbQ==}
collapse-white-space@2.1.0:
resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==}
@ -4110,10 +4058,6 @@ packages:
resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==}
engines: {node: '>=18'}
commander@14.0.3:
resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==}
engines: {node: '>=20'}
commander@2.20.3:
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
@ -4499,10 +4443,6 @@ packages:
domutils@3.2.2:
resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==}
dotenv@16.6.1:
resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==}
engines: {node: '>=12'}
echarts-for-react@3.0.5:
resolution: {integrity: sha512-YpEI5Ty7O/2nvCfQ7ybNa+S90DwE8KYZWacGvJW4luUqywP7qStQ+pxDlYOmr4jGDu10mhEkiAuMKcUlT4W5vg==}
peerDependencies:
@ -5612,10 +5552,6 @@ packages:
khroma@2.1.0:
resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==}
kleur@3.0.3:
resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
engines: {node: '>=6'}
knip@5.78.0:
resolution: {integrity: sha512-nB7i/fgiJl7WVxdv5lX4ZPfDt9/zrw/lOgZtyioy988xtFhKuFJCRdHWT1Zg9Avc0yaojvnmEuAXU8SeMblKww==}
engines: {node: '>=18.18.0'}
@ -5638,9 +5574,6 @@ packages:
resolution: {integrity: sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==}
engines: {node: '>=16.0.0'}
launch-ide@1.4.0:
resolution: {integrity: sha512-c2mcqZy7mNhzXiWoBFV0lDsEOfpSFGqqxKubPffhqcnv3GV0xpeGcHWLxYFm+jz1/5VAKp796QkyVV4++07eiw==}
layout-base@1.0.2:
resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==}
@ -6416,10 +6349,6 @@ packages:
points-on-path@0.2.1:
resolution: {integrity: sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==}
portfinder@1.0.38:
resolution: {integrity: sha512-rEwq/ZHlJIKw++XtLAO8PPuOQA/zaPJOZJ37BVuN97nLpMJeuDVLVGRwbFoBgLudgdTMP2hdRJP++H+8QOA3vg==}
engines: {node: '>= 10.12'}
postcss-import@15.1.0:
resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
engines: {node: '>=14.0.0'}
@ -6506,10 +6435,6 @@ packages:
resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==}
engines: {node: '>=6'}
prompts@2.4.2:
resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==}
engines: {node: '>= 6'}
prop-types@15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
@ -6678,13 +6603,6 @@ packages:
react: '>=16.3.0'
react-dom: '>=16.3.0'
react-scan@0.5.3:
resolution: {integrity: sha512-qde9PupmUf0L3MU1H6bjmoukZNbCXdMyTEwP4Gh8RQ4rZPd2GGNBgEKWszwLm96E8k+sGtMpc0B9P0KyFDP6Bw==}
hasBin: true
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-server-dom-webpack@19.2.4:
resolution: {integrity: sha512-zEhkWv6RhXDctC2N7yEUHg3751nvFg81ydHj8LTTZuukF/IF1gcOKqqAL6Ds+kS5HtDVACYPik0IvzkgYXPhlQ==}
engines: {node: '>=0.10.0'}
@ -7401,9 +7319,6 @@ packages:
engines: {node: '>=0.8.0'}
hasBin: true
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
undici-types@7.16.0:
resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
@ -7455,10 +7370,6 @@ packages:
resolution: {integrity: sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==}
engines: {node: '>=20.19.0'}
unplugin@2.1.0:
resolution: {integrity: sha512-us4j03/499KhbGP8BU7Hrzrgseo+KdfJYWcbcajCOqsAyb8Gk0Yn2kiUIcZISYCb1JFaZfIuG3b42HmguVOKCQ==}
engines: {node: '>=18.12.0'}
unplugin@2.3.11:
resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==}
engines: {node: '>=18.12.0'}
@ -8467,48 +8378,6 @@ snapshots:
picocolors: 1.1.1
sisteransi: 1.0.5
'@code-inspector/core@1.3.6':
dependencies:
'@vue/compiler-dom': 3.5.27
chalk: 4.1.2
dotenv: 16.6.1
launch-ide: 1.4.0
portfinder: 1.0.38
transitivePeerDependencies:
- supports-color
'@code-inspector/esbuild@1.3.6':
dependencies:
'@code-inspector/core': 1.3.6
transitivePeerDependencies:
- supports-color
'@code-inspector/mako@1.3.6':
dependencies:
'@code-inspector/core': 1.3.6
transitivePeerDependencies:
- supports-color
'@code-inspector/turbopack@1.3.6':
dependencies:
'@code-inspector/core': 1.3.6
'@code-inspector/webpack': 1.3.6
transitivePeerDependencies:
- supports-color
'@code-inspector/vite@1.3.6':
dependencies:
'@code-inspector/core': 1.3.6
chalk: 4.1.1
transitivePeerDependencies:
- supports-color
'@code-inspector/webpack@1.3.6':
dependencies:
'@code-inspector/core': 1.3.6
transitivePeerDependencies:
- supports-color
'@csstools/color-helpers@5.1.0': {}
'@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)':
@ -9752,11 +9621,6 @@ snapshots:
'@preact/signals-core@1.12.2': {}
'@preact/signals@1.3.2(preact@10.28.2)':
dependencies:
'@preact/signals-core': 1.12.2
preact: 10.28.2
'@radix-ui/primitive@1.1.3': {}
'@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.9)(react@19.2.4)':
@ -10329,18 +10193,18 @@ snapshots:
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
'@storybook/nextjs-vite@10.2.13(@babel/core@7.29.0)(esbuild@0.27.2)(next@16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.56.0)(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3))':
'@storybook/nextjs-vite@10.2.13(@babel/core@7.28.6)(esbuild@0.27.2)(next@16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.56.0)(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3))':
dependencies:
'@storybook/builder-vite': 10.2.13(esbuild@0.27.2)(rollup@4.56.0)(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3))
'@storybook/react': 10.2.13(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)
'@storybook/react-vite': 10.2.13(esbuild@0.27.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.56.0)(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3))
next: 16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2)
next: 16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2)
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
storybook: 10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
styled-jsx: 5.1.6(@babel/core@7.29.0)(react@19.2.4)
styled-jsx: 5.1.6(@babel/core@7.28.6)(react@19.2.4)
vite: 8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
vite-plugin-storybook-nextjs: 3.2.2(next@16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))
vite-plugin-storybook-nextjs: 3.2.2(next@16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))
optionalDependencies:
typescript: 5.9.3
transitivePeerDependencies:
@ -10869,10 +10733,6 @@ snapshots:
'@types/negotiator@0.6.4': {}
'@types/node@20.19.30':
dependencies:
undici-types: 6.21.0
'@types/node@24.10.12':
dependencies:
undici-types: 7.16.0
@ -10891,10 +10751,6 @@ snapshots:
dependencies:
'@types/react': 19.2.9
'@types/react-reconciler@0.28.9(@types/react@19.2.9)':
dependencies:
'@types/react': 19.2.9
'@types/react-slider@1.3.6':
dependencies:
'@types/react': 19.2.9
@ -11138,13 +10994,13 @@ snapshots:
dependencies:
unpic: 4.2.2
'@unpic/react@1.0.2(next@16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
'@unpic/react@1.0.2(next@16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
dependencies:
'@unpic/core': 1.0.3
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
optionalDependencies:
next: 16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2)
next: 16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2)
'@valibot/to-json-schema@1.5.0(valibot@1.2.0(typescript@5.9.3))':
dependencies:
@ -11286,7 +11142,7 @@ snapshots:
'@vue/compiler-core@3.5.27':
dependencies:
'@babel/parser': 7.28.6
'@babel/parser': 7.29.0
'@vue/shared': 3.5.27
entities: 7.0.1
estree-walker: 2.0.2
@ -11522,8 +11378,6 @@ snapshots:
astring@1.9.0: {}
async@3.2.6: {}
autoprefixer@10.4.21(postcss@8.5.6):
dependencies:
browserslist: 4.28.1
@ -11557,13 +11411,6 @@ snapshots:
binary-extensions@2.3.0: {}
bippy@0.5.30(@types/react@19.2.9)(react@19.2.4):
dependencies:
'@types/react-reconciler': 0.28.9(@types/react@19.2.9)
react: 19.2.4
transitivePeerDependencies:
- '@types/react'
birecord@0.1.1: {}
birpc@2.9.0: {}
@ -11641,11 +11488,6 @@ snapshots:
chai@6.2.2: {}
chalk@4.1.1:
dependencies:
ansi-styles: 4.3.0
supports-color: 7.2.0
chalk@4.1.2:
dependencies:
ansi-styles: 4.3.0
@ -11774,18 +11616,6 @@ snapshots:
- '@types/react'
- '@types/react-dom'
code-inspector-plugin@1.3.6:
dependencies:
'@code-inspector/core': 1.3.6
'@code-inspector/esbuild': 1.3.6
'@code-inspector/mako': 1.3.6
'@code-inspector/turbopack': 1.3.6
'@code-inspector/vite': 1.3.6
'@code-inspector/webpack': 1.3.6
chalk: 4.1.1
transitivePeerDependencies:
- supports-color
collapse-white-space@2.1.0: {}
color-convert@2.0.1:
@ -11812,8 +11642,6 @@ snapshots:
commander@13.1.0: {}
commander@14.0.3: {}
commander@2.20.3: {}
commander@4.1.1: {}
@ -12203,8 +12031,6 @@ snapshots:
domelementtype: 2.3.0
domhandler: 5.0.3
dotenv@16.6.1: {}
echarts-for-react@3.0.5(echarts@5.6.0)(react@19.2.4):
dependencies:
echarts: 5.6.0
@ -13440,9 +13266,9 @@ snapshots:
jiti@2.6.1: {}
jotai@2.16.1(@babel/core@7.29.0)(@babel/template@7.28.6)(@types/react@19.2.9)(react@19.2.4):
jotai@2.16.1(@babel/core@7.28.6)(@babel/template@7.28.6)(@types/react@19.2.9)(react@19.2.4):
optionalDependencies:
'@babel/core': 7.29.0
'@babel/core': 7.28.6
'@babel/template': 7.28.6
'@types/react': 19.2.9
react: 19.2.4
@ -13541,8 +13367,6 @@ snapshots:
khroma@2.1.0: {}
kleur@3.0.3: {}
knip@5.78.0(@types/node@24.10.12)(typescript@5.9.3):
dependencies:
'@nodelib/fs.walk': 1.2.8
@ -13576,11 +13400,6 @@ snapshots:
vscode-languageserver-textdocument: 1.0.12
vscode-uri: 3.0.8
launch-ide@1.4.0:
dependencies:
chalk: 4.1.2
dotenv: 16.6.1
layout-base@1.0.2: {}
layout-base@2.0.1: {}
@ -14365,7 +14184,7 @@ snapshots:
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
next@16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2):
next@16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2):
dependencies:
'@next/env': 16.1.5
'@swc/helpers': 0.5.15
@ -14374,7 +14193,7 @@ snapshots:
postcss: 8.4.31
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
styled-jsx: 5.1.6(@babel/core@7.29.0)(react@19.2.4)
styled-jsx: 5.1.6(@babel/core@7.28.6)(react@19.2.4)
optionalDependencies:
'@next/swc-darwin-arm64': 16.1.5
'@next/swc-darwin-x64': 16.1.5
@ -14420,12 +14239,12 @@ snapshots:
dependencies:
boolbase: 1.0.0
nuqs@2.8.6(next@16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react@19.2.4):
nuqs@2.8.6(next@16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react@19.2.4):
dependencies:
'@standard-schema/spec': 1.0.0
react: 19.2.4
optionalDependencies:
next: 16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2)
next: 16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2)
object-assign@4.1.1: {}
@ -14637,13 +14456,6 @@ snapshots:
path-data-parser: 0.1.0
points-on-curve: 0.2.0
portfinder@1.0.38:
dependencies:
async: 3.2.6
debug: 4.4.3
transitivePeerDependencies:
- supports-color
postcss-import@15.1.0(postcss@8.5.6):
dependencies:
postcss: 8.5.6
@ -14703,7 +14515,8 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.1
preact@10.28.2: {}
preact@10.28.2:
optional: true
prebuild-install@7.1.3:
dependencies:
@ -14731,11 +14544,6 @@ snapshots:
prismjs@1.30.0: {}
prompts@2.4.2:
dependencies:
kleur: 3.0.3
sisteransi: 1.0.5
prop-types@15.8.1:
dependencies:
loose-envify: 1.4.0
@ -14918,30 +14726,6 @@ snapshots:
react-draggable: 4.4.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
tslib: 2.6.2
react-scan@0.5.3(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.56.0):
dependencies:
'@babel/core': 7.29.0
'@babel/generator': 7.29.1
'@babel/types': 7.29.0
'@preact/signals': 1.3.2(preact@10.28.2)
'@rollup/pluginutils': 5.3.0(rollup@4.56.0)
'@types/node': 20.19.30
bippy: 0.5.30(@types/react@19.2.9)(react@19.2.4)
commander: 14.0.3
esbuild: 0.27.2
estree-walker: 3.0.3
picocolors: 1.1.1
preact: 10.28.2
prompts: 2.4.2
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
optionalDependencies:
unplugin: 2.1.0
transitivePeerDependencies:
- '@types/react'
- rollup
- supports-color
react-server-dom-webpack@19.2.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3)):
dependencies:
acorn-loose: 8.5.2
@ -15561,12 +15345,12 @@ snapshots:
dependencies:
inline-style-parser: 0.2.7
styled-jsx@5.1.6(@babel/core@7.29.0)(react@19.2.4):
styled-jsx@5.1.6(@babel/core@7.28.6)(react@19.2.4):
dependencies:
client-only: 0.0.1
react: 19.2.4
optionalDependencies:
'@babel/core': 7.29.0
'@babel/core': 7.28.6
stylis@4.3.6: {}
@ -15819,8 +15603,6 @@ snapshots:
uglify-js@3.19.3: {}
undici-types@6.21.0: {}
undici-types@7.16.0: {}
undici@7.21.0: {}
@ -15888,12 +15670,6 @@ snapshots:
pathe: 2.0.3
picomatch: 4.0.3
unplugin@2.1.0:
dependencies:
acorn: 8.16.0
webpack-virtual-modules: 0.6.2
optional: true
unplugin@2.3.11:
dependencies:
'@jridgewell/remapping': 2.3.5
@ -15981,9 +15757,9 @@ snapshots:
'@types/unist': 3.0.3
vfile-message: 4.0.3
vinext@https://pkg.pr.new/hyoban/vinext@556a6d6(next@16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3)):
vinext@https://pkg.pr.new/hyoban/vinext@556a6d6(next@16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3)):
dependencies:
'@unpic/react': 1.0.2(next@16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@unpic/react': 1.0.2(next@16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@vercel/og': 0.8.6
'@vitejs/plugin-rsc': 0.5.21(react-dom@19.2.4(react@19.2.4))(react-server-dom-webpack@19.2.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3)))(react@19.2.4)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))
magic-string: 0.30.21
@ -16038,13 +15814,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
vite-plugin-storybook-nextjs@3.2.2(next@16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)):
vite-plugin-storybook-nextjs@3.2.2(next@16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)):
dependencies:
'@next/env': 16.0.0
image-size: 2.0.2
magic-string: 0.30.21
module-alias: 2.3.4
next: 16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2)
next: 16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2)
storybook: 10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
ts-dedent: 2.2.0
vite: 8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)

View File

@ -1,162 +1,16 @@
import type { Plugin } from 'vite'
import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import react from '@vitejs/plugin-react'
import { codeInspectorPlugin } from 'code-inspector-plugin'
import vinext from 'vinext'
import { defineConfig } from 'vite'
import Inspect from 'vite-plugin-inspect'
import tsconfigPaths from 'vite-tsconfig-paths'
import { customI18nHmrPlugin } from './plugins/vite/custom-i18n-hmr'
import { reactGrabOpenFilePlugin } from './plugins/vite/react-grab-open-file'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const projectRoot = path.dirname(fileURLToPath(import.meta.url))
const isCI = !!process.env.CI
const inspectorPort = 5678
const inspectorInjectTarget = path.resolve(__dirname, 'app/components/browser-initializer.tsx')
const inspectorRuntimeFile = path.resolve(
__dirname,
`node_modules/code-inspector-plugin/dist/append-code-${inspectorPort}.js`,
)
const getInspectorRuntimeSnippet = (): string => {
if (!fs.existsSync(inspectorRuntimeFile))
return ''
const raw = fs.readFileSync(inspectorRuntimeFile, 'utf-8')
// Remove the helper module default export from append file to avoid duplicate default exports.
return raw.replace(
/\s*export default function CodeInspectorEmptyElement\(\)\s*\{[\s\S]*$/,
'',
)
}
const normalizeInspectorModuleId = (id: string): string => {
const withoutQuery = id.split('?', 1)[0]
// Vite/vinext may pass absolute fs modules as "/@fs/<abs-path>".
if (withoutQuery.startsWith('/@fs/'))
return withoutQuery.slice('/@fs'.length)
return withoutQuery
}
const createCodeInspectorPlugin = (): Plugin => {
return codeInspectorPlugin({
bundler: 'vite',
port: inspectorPort,
injectTo: inspectorInjectTarget,
exclude: [/^(?!.*\.(?:js|ts|mjs|mts|jsx|tsx|vue|svelte|html)(?:$|\?)).*/],
}) as Plugin
}
const createForceInspectorClientInjectionPlugin = (): Plugin => {
const clientSnippet = getInspectorRuntimeSnippet()
return {
name: 'vinext-force-code-inspector-client',
apply: 'serve',
enforce: 'pre',
transform(code, id) {
if (!clientSnippet)
return null
const cleanId = normalizeInspectorModuleId(id)
if (cleanId !== inspectorInjectTarget)
return null
if (code.includes('code-inspector-component'))
return null
return `${clientSnippet}\n${code}`
},
}
}
function customI18nHmrPlugin(): Plugin {
const injectTarget = inspectorInjectTarget
const i18nHmrClientMarker = 'custom-i18n-hmr-client'
const i18nHmrClientSnippet = `/* ${i18nHmrClientMarker} */
if (import.meta.hot) {
const getI18nUpdateTarget = (file) => {
const match = file.match(/[/\\\\]i18n[/\\\\]([^/\\\\]+)[/\\\\]([^/\\\\]+)\\.json$/)
if (!match)
return null
const [, locale, namespaceFile] = match
return { locale, namespaceFile }
}
import.meta.hot.on('i18n-update', async ({ file, content }) => {
const target = getI18nUpdateTarget(file)
if (!target)
return
const [{ getI18n }, { camelCase }] = await Promise.all([
import('react-i18next'),
import('es-toolkit/string'),
])
const i18n = getI18n()
if (!i18n)
return
if (target.locale !== i18n.language)
return
let resources
try {
resources = JSON.parse(content)
}
catch {
return
}
const namespace = camelCase(target.namespaceFile)
i18n.addResourceBundle(target.locale, namespace, resources, true, true)
i18n.emit('languageChanged', i18n.language)
})
}
`
const injectI18nHmrClient = (code: string) => {
if (code.includes(i18nHmrClientMarker))
return code
const useClientMatch = code.match(/(['"])use client\1;?\s*\n/)
if (!useClientMatch)
return `${i18nHmrClientSnippet}\n${code}`
const insertAt = (useClientMatch.index ?? 0) + useClientMatch[0].length
return `${code.slice(0, insertAt)}\n${i18nHmrClientSnippet}\n${code.slice(insertAt)}`
}
return {
name: 'custom-i18n-hmr',
apply: 'serve',
handleHotUpdate({ file, server }) {
if (file.endsWith('.json') && file.includes('/i18n/')) {
server.ws.send({
type: 'custom',
event: 'i18n-update',
data: {
file,
content: fs.readFileSync(file, 'utf-8'),
},
})
// return empty array to prevent the default HMR
return []
}
},
transform(code, id) {
const cleanId = normalizeInspectorModuleId(id)
if (cleanId !== injectTarget)
return null
const nextCode = injectI18nHmrClient(code)
if (nextCode === code)
return null
return { code: nextCode, map: null }
},
}
}
const browserInitializerInjectTarget = path.resolve(projectRoot, 'app/components/browser-initializer.tsx')
export default defineConfig(({ mode }) => {
const isTest = mode === 'test'
@ -176,7 +30,7 @@ export default defineConfig(({ mode }) => {
if (id.endsWith('.mdx'))
return { code: 'export default () => null', map: null }
},
} as Plugin,
},
]
: isStorybook
? [
@ -185,15 +39,17 @@ export default defineConfig(({ mode }) => {
]
: [
Inspect(),
createCodeInspectorPlugin(),
createForceInspectorClientInjectionPlugin(),
react(),
vinext(),
customI18nHmrPlugin(),
customI18nHmrPlugin({ injectTarget: browserInitializerInjectTarget }),
reactGrabOpenFilePlugin({
injectTarget: browserInitializerInjectTarget,
projectRoot,
}),
],
resolve: {
alias: {
'~@': __dirname,
'~@': projectRoot,
},
},