Merge remote-tracking branch 'origin/main' into feat/model-plugins-implementing

This commit is contained in:
yyh
2026-03-09 23:42:04 +08:00
14 changed files with 5865 additions and 2616 deletions

View File

@ -25,14 +25,11 @@ updates:
interval: "weekly"
open-pull-requests-limit: 2
ignore:
- dependency-name: "@sentry/react"
- dependency-name: "ky"
- dependency-name: "tailwind-merge"
update-types: ["version-update:semver-major"]
- dependency-name: "tailwindcss"
update-types: ["version-update:semver-major"]
- dependency-name: "echarts"
update-types: ["version-update:semver-major"]
- dependency-name: "uuid"
update-types: ["version-update:semver-major"]
- dependency-name: "react-markdown"
update-types: ["version-update:semver-major"]
- dependency-name: "react-syntax-highlighter"

View File

@ -84,4 +84,27 @@ jobs:
run: |
uvx --python 3.13 mdformat . --exclude ".agents/skills/**"
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
package_json_file: web/package.json
run_install: false
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 24
cache: pnpm
cache-dependency-path: ./web/pnpm-lock.yaml
- name: Install web dependencies
run: |
cd web
pnpm install --frozen-lockfile
- name: ESLint autofix
run: |
cd web
pnpm eslint --concurrency=2 --prune-suppressions
- uses: autofix-ci/action@635ffb0c9798bd160680f18fd73371e355b85f27

View File

@ -172,12 +172,8 @@ describe('dataset-config/card-item', () => {
const [editButton] = within(card).getAllByRole('button', { hidden: true })
await user.click(editButton)
expect(screen.getByText('Mock settings modal')).toBeInTheDocument()
await waitFor(() => {
expect(screen.getByRole('dialog')).toBeVisible()
})
fireEvent.click(screen.getByText('Save changes'))
expect(await screen.findByText('Mock settings modal')).toBeInTheDocument()
fireEvent.click(await screen.findByText('Save changes'))
await waitFor(() => {
expect(onSave).toHaveBeenCalledWith(expect.objectContaining({ name: 'Updated dataset' }))
@ -194,7 +190,7 @@ describe('dataset-config/card-item', () => {
const card = screen.getByText(dataset.name).closest('.group') as HTMLElement
const buttons = within(card).getAllByRole('button', { hidden: true })
const deleteButton = buttons[buttons.length - 1]
const deleteButton = buttons.at(-1)!
expect(deleteButton.className).not.toContain('action-btn-destructive')
@ -233,7 +229,7 @@ describe('dataset-config/card-item', () => {
await user.click(editButton)
expect(screen.getByText('Mock settings modal')).toBeInTheDocument()
const overlay = Array.from(document.querySelectorAll('[class]'))
const overlay = [...document.querySelectorAll('[class]')]
.find(element => element.className.toString().includes('bg-black/30'))
expect(overlay).toBeInTheDocument()

View File

@ -164,7 +164,7 @@ const VoiceParamConfig = ({
</div>
<div className="flex items-center gap-1">
<Listbox
value={voiceItem ?? {}}
value={voiceItem}
disabled={!languageItem}
onChange={(value: Item) => {
handleChange({

View File

@ -1,55 +1,72 @@
import type { FormType } from '../../..'
import type { CustomActionsProps } from '../actions'
import { fireEvent, render, screen } from '@testing-library/react'
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { formContext } from '../../..'
import Actions from '../actions'
const renderWithForm = ({
canSubmit,
isSubmitting,
CustomActions,
}: {
canSubmit: boolean
isSubmitting: boolean
const mockFormState = vi.hoisted(() => ({
canSubmit: true,
isSubmitting: false,
}))
vi.mock('@tanstack/react-form', async () => {
const actual = await vi.importActual<typeof import('@tanstack/react-form')>('@tanstack/react-form')
return {
...actual,
useStore: (_store: unknown, selector: (state: typeof mockFormState) => unknown) => selector(mockFormState),
}
})
type RenderWithFormOptions = {
canSubmit?: boolean
isSubmitting?: boolean
CustomActions?: (props: CustomActionsProps) => React.ReactNode
}) => {
const submitSpy = vi.fn()
const state = {
canSubmit,
isSubmitting,
}
onSubmit?: () => void
}
const renderWithForm = ({
canSubmit = true,
isSubmitting = false,
CustomActions,
onSubmit = vi.fn(),
}: RenderWithFormOptions = {}) => {
mockFormState.canSubmit = canSubmit
mockFormState.isSubmitting = isSubmitting
const form = {
store: {
state,
subscribe: () => () => {},
},
handleSubmit: submitSpy,
store: {},
handleSubmit: onSubmit,
}
const TestComponent = () => {
return (
<formContext.Provider value={form as unknown as FormType}>
<Actions
CustomActions={CustomActions}
/>
</formContext.Provider>
)
}
render(
<formContext.Provider value={form as unknown as FormType}>
<Actions CustomActions={CustomActions} />
</formContext.Provider>,
)
render(<TestComponent />)
return { submitSpy }
return { onSubmit }
}
describe('Actions', () => {
beforeEach(() => {
vi.clearAllMocks()
})
it('should disable submit button when form cannot submit', () => {
renderWithForm({ canSubmit: false, isSubmitting: false })
renderWithForm({ canSubmit: false })
expect(screen.getByRole('button', { name: 'common.operation.submit' })).toBeDisabled()
})
it('should call form submit when users click submit button', () => {
const { submitSpy } = renderWithForm({ canSubmit: true, isSubmitting: false })
it('should call form submit when users click submit button', async () => {
const submitSpy = vi.fn()
renderWithForm({ onSubmit: submitSpy })
fireEvent.click(screen.getByRole('button', { name: 'common.operation.submit' }))
expect(submitSpy).toHaveBeenCalledTimes(1)
await waitFor(() => {
expect(submitSpy).toHaveBeenCalledTimes(1)
})
})
it('should render custom actions when provided', () => {
@ -60,15 +77,14 @@ describe('Actions', () => {
))
renderWithForm({
canSubmit: true,
isSubmitting: true,
CustomActions: customActionsSpy,
})
expect(screen.queryByRole('button', { name: 'common.operation.submit' })).not.toBeInTheDocument()
expect(screen.getByText('custom-true-true')).toBeInTheDocument()
expect(screen.getByText('custom-false-true')).toBeInTheDocument()
expect(customActionsSpy).toHaveBeenCalledWith(expect.objectContaining({
isSubmitting: true,
form: expect.any(Object),
isSubmitting: false,
canSubmit: true,
}))
})

View File

@ -100,11 +100,11 @@ const Select: FC<ISelectProps> = ({
disabled={disabled}
value={selectedItem}
className={className}
onChange={(value: Item) => {
onChange={(value) => {
if (!disabled) {
setSelectedItem(value)
setOpen(false)
onSelect(value)
onSelect(value as Item)
}
}}
>
@ -224,10 +224,10 @@ const SimpleSelect: FC<ISelectProps> = ({
<Listbox
ref={listboxRef}
value={selectedItem}
onChange={(value: Item) => {
onChange={(value) => {
if (!disabled) {
setSelectedItem(value)
onSelect(value)
onSelect(value as Item)
}
}}
>

View File

@ -1,4 +1,5 @@
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
import { act, render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import SVGRenderer from '..'
const mockClick = vi.fn()
@ -117,6 +118,7 @@ describe('SVGRenderer', () => {
})
it('closes image preview on cancel', async () => {
const user = userEvent.setup()
render(<SVGRenderer content={validSvg} />)
await waitFor(() => {
@ -129,9 +131,11 @@ describe('SVGRenderer', () => {
expect(screen.getByAltText('Preview')).toBeInTheDocument()
fireEvent.keyDown(document, { key: 'Escape' })
await user.click(screen.getByTestId('image-preview-close-button'))
expect(screen.queryByAltText('Preview')).not.toBeInTheDocument()
await waitFor(() => {
expect(screen.queryByAltText('Preview')).not.toBeInTheDocument()
})
})
})
})

View File

@ -1,4 +1,5 @@
import { act, cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import Operations from '../operations'
@ -355,16 +356,14 @@ describe('Operations', () => {
})
it('should show rename modal when rename is clicked', async () => {
const user = userEvent.setup()
render(<Operations {...defaultProps} />)
await openPopover()
const renameButton = screen.getByText('datasetDocuments.list.table.rename')
await act(async () => {
fireEvent.click(renameButton)
})
// Rename modal should be shown
await waitFor(() => {
expect(screen.getByDisplayValue('Test Document')).toBeInTheDocument()
})
const renameAction = screen.getByText('datasetDocuments.list.table.rename').parentElement as HTMLElement
await user.click(renameAction)
const renameInput = await screen.findByRole('textbox')
expect(renameInput).toHaveValue('Test Document')
})
it('should call sync for notion data source', async () => {

View File

@ -5,6 +5,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { ToastContext } from '@/app/components/base/toast/context'
import { ProcessMode } from '@/models/datasets'
import * as datasetsService from '@/service/datasets'
import * as useDataset from '@/service/knowledge/use-dataset'
@ -13,8 +14,22 @@ import { IndexingType } from '../../../../create/step-two'
import { DocumentContext } from '../../context'
import EmbeddingDetail from '../index'
const { mockNotify, mockClose } = vi.hoisted(() => ({
mockNotify: vi.fn(),
mockClose: vi.fn(),
}))
vi.mock('@/service/datasets')
vi.mock('@/service/knowledge/use-dataset')
vi.mock('@/app/components/base/toast/context', async () => {
const { createContext } = await vi.importActual<typeof import('use-context-selector')>('use-context-selector')
return {
ToastContext: createContext({
notify: mockNotify,
close: mockClose,
}),
}
})
const mockFetchIndexingStatus = vi.mocked(datasetsService.fetchIndexingStatus)
const mockPauseDocIndexing = vi.mocked(datasetsService.pauseDocIndexing)
@ -32,9 +47,11 @@ const createWrapper = (contextValue: DocumentContextValue = { datasetId: 'ds1',
const queryClient = createTestQueryClient()
return ({ children }: { children: ReactNode }) => (
<QueryClientProvider client={queryClient}>
<DocumentContext.Provider value={contextValue}>
{children}
</DocumentContext.Provider>
<ToastContext.Provider value={{ notify: mockNotify, close: vi.fn() }}>
<DocumentContext.Provider value={contextValue}>
{children}
</DocumentContext.Provider>
</ToastContext.Provider>
</QueryClientProvider>
)
}

File diff suppressed because it is too large Load Diff

View File

@ -15,12 +15,24 @@ const config: KnipConfig = {
ignoreBinaries: [
'only-allow',
],
ignoreDependencies: [],
ignoreDependencies: [
'@iconify-json/*',
'@storybook/addon-onboarding',
// vinext related
'react-server-dom-webpack',
'@vitejs/plugin-rsc',
'@mdx-js/rollup',
'@tsslint/compat-eslint',
'@tsslint/config',
],
rules: {
files: 'warn',
dependencies: 'warn',
devDependencies: 'warn',
optionalPeerDependencies: 'warn',
dependencies: 'error',
devDependencies: 'error',
optionalPeerDependencies: 'error',
unlisted: 'warn',
unresolved: 'warn',
exports: 'warn',

View File

@ -3,7 +3,7 @@
"type": "module",
"version": "1.13.0",
"private": true,
"packageManager": "pnpm@10.27.0",
"packageManager": "pnpm@10.31.0",
"imports": {
"#i18n": {
"react-server": "./i18n-config/lib.server.ts",
@ -61,13 +61,13 @@
"knip": "knip"
},
"dependencies": {
"@amplitude/analytics-browser": "2.33.1",
"@amplitude/plugin-session-replay-browser": "1.23.6",
"@amplitude/analytics-browser": "2.36.2",
"@amplitude/plugin-session-replay-browser": "1.25.20",
"@base-ui/react": "1.2.0",
"@emoji-mart/data": "1.2.1",
"@floating-ui/react": "0.26.28",
"@formatjs/intl-localematcher": "0.5.10",
"@headlessui/react": "2.2.1",
"@floating-ui/react": "0.27.19",
"@formatjs/intl-localematcher": "0.8.1",
"@headlessui/react": "2.2.9",
"@heroicons/react": "2.2.0",
"@lexical/code": "0.41.0",
"@lexical/link": "0.41.0",
@ -77,68 +77,68 @@
"@lexical/text": "0.41.0",
"@lexical/utils": "0.41.0",
"@monaco-editor/react": "4.7.0",
"@octokit/core": "6.1.6",
"@octokit/request-error": "6.1.8",
"@octokit/core": "7.0.6",
"@octokit/request-error": "7.1.0",
"@orpc/client": "1.13.6",
"@orpc/contract": "1.13.6",
"@orpc/openapi-client": "1.13.6",
"@orpc/tanstack-query": "1.13.6",
"@remixicon/react": "4.7.0",
"@sentry/react": "8.55.0",
"@remixicon/react": "4.9.0",
"@sentry/react": "10.42.0",
"@svgdotjs/svg.js": "3.2.5",
"@t3-oss/env-nextjs": "0.13.10",
"@tailwindcss/typography": "0.5.19",
"@tanstack/react-form": "1.23.7",
"@tanstack/react-query": "5.90.5",
"abcjs": "6.5.2",
"ahooks": "3.9.5",
"@tanstack/react-form": "1.28.4",
"@tanstack/react-query": "5.90.21",
"abcjs": "6.6.2",
"ahooks": "3.9.6",
"class-variance-authority": "0.7.1",
"clsx": "2.1.1",
"cmdk": "1.1.1",
"copy-to-clipboard": "3.3.3",
"cron-parser": "5.4.0",
"cron-parser": "5.5.0",
"dayjs": "1.11.19",
"decimal.js": "10.6.0",
"dompurify": "3.3.2",
"echarts": "5.6.0",
"echarts-for-react": "3.0.5",
"elkjs": "0.9.3",
"echarts": "6.0.0",
"echarts-for-react": "3.0.6",
"elkjs": "0.11.1",
"embla-carousel-autoplay": "8.6.0",
"embla-carousel-react": "8.6.0",
"emoji-mart": "5.6.0",
"es-toolkit": "1.43.0",
"es-toolkit": "1.45.1",
"fast-deep-equal": "3.1.3",
"foxact": "0.2.52",
"foxact": "0.2.54",
"html-entities": "2.6.0",
"html-to-image": "1.11.13",
"i18next": "25.7.3",
"i18next": "25.8.16",
"i18next-resources-to-backend": "1.2.1",
"immer": "11.1.0",
"jotai": "2.16.1",
"immer": "11.1.4",
"jotai": "2.18.0",
"js-audio-recorder": "1.0.7",
"js-cookie": "3.0.5",
"js-yaml": "4.1.1",
"jsonschema": "1.5.0",
"katex": "0.16.25",
"katex": "0.16.38",
"ky": "1.12.0",
"lamejs": "1.2.1",
"lexical": "0.41.0",
"mermaid": "11.11.0",
"mermaid": "11.13.0",
"mime": "4.1.0",
"mitt": "3.0.1",
"negotiator": "1.0.0",
"next": "16.1.5",
"next": "16.1.6",
"next-themes": "0.4.6",
"nuqs": "2.8.6",
"pinyin-pro": "3.27.0",
"nuqs": "2.8.9",
"pinyin-pro": "3.28.0",
"qrcode.react": "4.2.0",
"qs": "6.14.2",
"qs": "6.15.0",
"react": "19.2.4",
"react-18-input-autosize": "3.0.0",
"react-dom": "19.2.4",
"react-easy-crop": "5.5.3",
"react-hotkeys-hook": "4.6.2",
"react-i18next": "16.5.0",
"react-easy-crop": "5.5.6",
"react-hotkeys-hook": "5.2.4",
"react-i18next": "16.5.6",
"react-markdown": "9.1.0",
"react-multi-email": "1.0.25",
"react-papaparse": "4.4.0",
@ -155,44 +155,44 @@
"remark-gfm": "4.0.1",
"remark-math": "6.0.0",
"scheduler": "0.27.0",
"semver": "7.7.3",
"sharp": "0.33.5",
"sortablejs": "1.15.6",
"semver": "7.7.4",
"sharp": "0.34.5",
"sortablejs": "1.15.7",
"string-ts": "2.3.1",
"tailwind-merge": "2.6.1",
"tldts": "7.0.17",
"tldts": "7.0.25",
"use-context-selector": "2.0.0",
"uuid": "10.0.0",
"uuid": "13.0.0",
"zod": "4.3.6",
"zundo": "2.3.0",
"zustand": "5.0.9"
"zustand": "5.0.11"
},
"devDependencies": {
"@antfu/eslint-config": "7.6.1",
"@antfu/eslint-config": "7.7.0",
"@chromatic-com/storybook": "5.0.1",
"@egoist/tailwindcss-icons": "1.9.2",
"@eslint-react/eslint-plugin": "2.13.0",
"@iconify-json/heroicons": "1.2.3",
"@iconify-json/ri": "1.2.9",
"@iconify-json/ri": "1.2.10",
"@mdx-js/loader": "3.1.1",
"@mdx-js/react": "3.1.1",
"@mdx-js/rollup": "3.1.1",
"@next/eslint-plugin-next": "16.1.6",
"@next/mdx": "16.1.5",
"@next/mdx": "16.1.6",
"@rgrove/parse-xml": "4.2.0",
"@storybook/addon-docs": "10.2.13",
"@storybook/addon-links": "10.2.13",
"@storybook/addon-onboarding": "10.2.13",
"@storybook/addon-themes": "10.2.13",
"@storybook/nextjs-vite": "10.2.13",
"@storybook/react": "10.2.13",
"@storybook/addon-docs": "10.2.16",
"@storybook/addon-links": "10.2.16",
"@storybook/addon-onboarding": "10.2.16",
"@storybook/addon-themes": "10.2.16",
"@storybook/nextjs-vite": "10.2.16",
"@storybook/react": "10.2.16",
"@tanstack/eslint-plugin-query": "5.91.4",
"@tanstack/react-devtools": "0.9.2",
"@tanstack/react-form-devtools": "0.2.12",
"@tanstack/react-query-devtools": "5.90.2",
"@tanstack/react-devtools": "0.9.10",
"@tanstack/react-form-devtools": "0.2.17",
"@tanstack/react-query-devtools": "5.91.3",
"@testing-library/dom": "10.4.1",
"@testing-library/jest-dom": "6.9.1",
"@testing-library/react": "16.3.0",
"@testing-library/react": "16.3.2",
"@testing-library/user-event": "14.6.1",
"@tsslint/cli": "3.0.2",
"@tsslint/compat-eslint": "3.0.2",
@ -200,51 +200,49 @@
"@types/js-cookie": "3.0.6",
"@types/js-yaml": "4.0.9",
"@types/negotiator": "0.6.4",
"@types/node": "24.10.12",
"@types/node": "25.3.5",
"@types/postcss-js": "4.1.0",
"@types/qs": "6.14.0",
"@types/react": "19.2.9",
"@types/qs": "6.15.0",
"@types/react": "19.2.14",
"@types/react-dom": "19.2.3",
"@types/react-slider": "1.3.6",
"@types/react-syntax-highlighter": "15.5.13",
"@types/react-window": "1.8.8",
"@types/semver": "7.7.1",
"@types/sortablejs": "1.15.8",
"@types/uuid": "10.0.0",
"@types/sortablejs": "1.15.9",
"@typescript-eslint/parser": "8.56.1",
"@typescript/native-preview": "7.0.0-dev.20251209.1",
"@typescript/native-preview": "7.0.0-dev.20260309.1",
"@vitejs/plugin-react": "5.1.4",
"@vitejs/plugin-rsc": "0.5.21",
"@vitest/coverage-v8": "4.0.18",
"agentation": "2.3.0",
"autoprefixer": "10.4.21",
"code-inspector-plugin": "1.4.2",
"cross-env": "10.1.0",
"eslint": "10.0.2",
"eslint-plugin-better-tailwindcss": "https://pkg.pr.new/hyoban/eslint-plugin-better-tailwindcss@a520d15",
"eslint-plugin-hyoban": "0.11.2",
"autoprefixer": "10.4.27",
"code-inspector-plugin": "1.4.4",
"eslint": "10.0.3",
"eslint-plugin-better-tailwindcss": "4.3.2",
"eslint-plugin-hyoban": "0.14.1",
"eslint-plugin-react-hooks": "7.0.1",
"eslint-plugin-react-refresh": "0.5.2",
"eslint-plugin-sonarjs": "4.0.0",
"eslint-plugin-storybook": "10.2.13",
"eslint-plugin-sonarjs": "4.0.1",
"eslint-plugin-storybook": "10.2.16",
"husky": "9.1.7",
"iconify-import-svg": "0.1.2",
"jsdom": "27.3.0",
"jsdom": "28.1.0",
"jsdom-testing-mocks": "1.16.0",
"knip": "5.78.0",
"lint-staged": "15.5.2",
"nock": "14.0.10",
"postcss": "8.5.6",
"postcss-js": "5.0.3",
"knip": "5.86.0",
"lint-staged": "16.3.2",
"nock": "14.0.11",
"postcss": "8.5.8",
"postcss-js": "5.1.0",
"react-server-dom-webpack": "19.2.4",
"sass": "1.93.2",
"storybook": "10.2.13",
"sass": "1.97.3",
"storybook": "10.2.16",
"tailwindcss": "3.4.19",
"tsx": "4.21.0",
"typescript": "5.9.3",
"uglify-js": "3.19.3",
"vinext": "https://pkg.pr.new/vinext@1a2fd61",
"vite": "8.0.0-beta.16",
"vite": "8.0.0-beta.18",
"vite-plugin-inspect": "11.3.3",
"vite-tsconfig-paths": "6.1.1",
"vitest": "4.0.18",
@ -253,50 +251,48 @@
"pnpm": {
"overrides": {
"@lexical/code": "npm:lexical-code-no-prism@0.41.0",
"@monaco-editor/loader": "1.5.0",
"@monaco-editor/loader": "1.7.0",
"@nolyfill/safe-buffer": "npm:safe-buffer@^5.2.1",
"@stylistic/eslint-plugin": "https://pkg.pr.new/@stylistic/eslint-plugin@258f9d8",
"array-includes": "npm:@nolyfill/array-includes@^1",
"array.prototype.findlast": "npm:@nolyfill/array.prototype.findlast@^1",
"array.prototype.findlastindex": "npm:@nolyfill/array.prototype.findlastindex@^1",
"array.prototype.flat": "npm:@nolyfill/array.prototype.flat@^1",
"array.prototype.flatmap": "npm:@nolyfill/array.prototype.flatmap@^1",
"array.prototype.tosorted": "npm:@nolyfill/array.prototype.tosorted@^1",
"assert": "npm:@nolyfill/assert@^1",
"brace-expansion": "~2.0",
"array-includes": "npm:@nolyfill/array-includes@^1.0.44",
"array.prototype.findlast": "npm:@nolyfill/array.prototype.findlast@^1.0.44",
"array.prototype.findlastindex": "npm:@nolyfill/array.prototype.findlastindex@^1.0.44",
"array.prototype.flat": "npm:@nolyfill/array.prototype.flat@^1.0.44",
"array.prototype.flatmap": "npm:@nolyfill/array.prototype.flatmap@^1.0.44",
"array.prototype.tosorted": "npm:@nolyfill/array.prototype.tosorted@^1.0.44",
"assert": "npm:@nolyfill/assert@^1.0.26",
"brace-expansion@<2.0.2": "2.0.2",
"canvas": "^3.2.0",
"canvas": "^3.2.1",
"devalue@<5.3.2": "5.3.2",
"es-iterator-helpers": "npm:@nolyfill/es-iterator-helpers@^1",
"es-iterator-helpers": "npm:@nolyfill/es-iterator-helpers@^1.0.21",
"esbuild@<0.27.2": "0.27.2",
"glob@>=10.2.0,<10.5.0": "11.1.0",
"hasown": "npm:@nolyfill/hasown@^1",
"is-arguments": "npm:@nolyfill/is-arguments@^1",
"is-core-module": "npm:@nolyfill/is-core-module@^1",
"is-generator-function": "npm:@nolyfill/is-generator-function@^1",
"is-typed-array": "npm:@nolyfill/is-typed-array@^1",
"isarray": "npm:@nolyfill/isarray@^1",
"object.assign": "npm:@nolyfill/object.assign@^1",
"object.entries": "npm:@nolyfill/object.entries@^1",
"object.fromentries": "npm:@nolyfill/object.fromentries@^1",
"object.groupby": "npm:@nolyfill/object.groupby@^1",
"object.values": "npm:@nolyfill/object.values@^1",
"pbkdf2": "~3.1.3",
"hasown": "npm:@nolyfill/hasown@^1.0.44",
"is-arguments": "npm:@nolyfill/is-arguments@^1.0.44",
"is-core-module": "npm:@nolyfill/is-core-module@^1.0.39",
"is-generator-function": "npm:@nolyfill/is-generator-function@^1.0.44",
"is-typed-array": "npm:@nolyfill/is-typed-array@^1.0.44",
"isarray": "npm:@nolyfill/isarray@^1.0.44",
"object.assign": "npm:@nolyfill/object.assign@^1.0.44",
"object.entries": "npm:@nolyfill/object.entries@^1.0.44",
"object.fromentries": "npm:@nolyfill/object.fromentries@^1.0.44",
"object.groupby": "npm:@nolyfill/object.groupby@^1.0.44",
"object.values": "npm:@nolyfill/object.values@^1.0.44",
"pbkdf2": "~3.1.5",
"pbkdf2@<3.1.3": "3.1.3",
"prismjs": "~1.30",
"prismjs@<1.30.0": "1.30.0",
"safe-buffer": "^5.2.1",
"safe-regex-test": "npm:@nolyfill/safe-regex-test@^1",
"safer-buffer": "npm:@nolyfill/safer-buffer@^1",
"side-channel": "npm:@nolyfill/side-channel@^1",
"safe-regex-test": "npm:@nolyfill/safe-regex-test@^1.0.44",
"safer-buffer": "npm:@nolyfill/safer-buffer@^1.0.44",
"side-channel": "npm:@nolyfill/side-channel@^1.0.44",
"solid-js": "1.9.11",
"string-width": "~4.2.3",
"string.prototype.includes": "npm:@nolyfill/string.prototype.includes@^1",
"string.prototype.matchall": "npm:@nolyfill/string.prototype.matchall@^1",
"string.prototype.repeat": "npm:@nolyfill/string.prototype.repeat@^1",
"string.prototype.trimend": "npm:@nolyfill/string.prototype.trimend@^1",
"typed-array-buffer": "npm:@nolyfill/typed-array-buffer@^1",
"which-typed-array": "npm:@nolyfill/which-typed-array@^1"
"string-width": "~8.2.0",
"string.prototype.includes": "npm:@nolyfill/string.prototype.includes@^1.0.44",
"string.prototype.matchall": "npm:@nolyfill/string.prototype.matchall@^1.0.44",
"string.prototype.repeat": "npm:@nolyfill/string.prototype.repeat@^1.0.44",
"string.prototype.trimend": "npm:@nolyfill/string.prototype.trimend@^1.0.44",
"typed-array-buffer": "npm:@nolyfill/typed-array-buffer@^1.0.44",
"which-typed-array": "npm:@nolyfill/which-typed-array@^1.0.44"
},
"ignoredBuiltDependencies": [
"canvas",
@ -309,6 +305,6 @@
]
},
"lint-staged": {
"*": "eslint --fix"
"*": "eslint --fix --pass-on-unpruned-suppressions"
}
}

4616
web/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -67,10 +67,11 @@ if (typeof globalThis.IntersectionObserver === 'undefined') {
globalThis.IntersectionObserver = class {
readonly root: Element | Document | null = null
readonly rootMargin: string = ''
readonly scrollMargin: string = ''
readonly thresholds: ReadonlyArray<number> = []
constructor(_callback: IntersectionObserverCallback, _options?: IntersectionObserverInit) { /* noop */ }
observe() { /* noop */ }
unobserve() { /* noop */ }
observe(_target: Element) { /* noop */ }
unobserve(_target: Element) { /* noop */ }
disconnect() { /* noop */ }
takeRecords(): IntersectionObserverEntry[] { return [] }
}