[web] Recreate workbench with Overleaf styles (#29651)
GitOrigin-RevId: 52ca336f70b29edf6e39cf95aa164f3ae32c0a79
This commit is contained in:
committed by
Copybot
parent
b1009d3b1f
commit
7b331b0222
Generated
+360
-3706
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,6 @@
|
||||
.eslint*
|
||||
.prettier*
|
||||
libraries/access-token-encryptor/**
|
||||
libraries/ai/**
|
||||
libraries/eslint-plugin/**
|
||||
libraries/fetch-utils/**
|
||||
libraries/logger/**
|
||||
|
||||
@@ -24,7 +24,6 @@ FROM base AS deps-prod
|
||||
|
||||
COPY package.json package-lock.json /overleaf/
|
||||
COPY libraries/access-token-encryptor/package.json /overleaf/libraries/access-token-encryptor/package.json
|
||||
COPY libraries/ai/package.json /overleaf/libraries/ai/package.json
|
||||
COPY libraries/eslint-plugin/package.json /overleaf/libraries/eslint-plugin/package.json
|
||||
COPY libraries/fetch-utils/package.json /overleaf/libraries/fetch-utils/package.json
|
||||
COPY libraries/logger/package.json /overleaf/libraries/logger/package.json
|
||||
@@ -59,7 +58,6 @@ FROM deps AS dev
|
||||
ARG SENTRY_RELEASE
|
||||
ENV SENTRY_RELEASE=$SENTRY_RELEASE
|
||||
COPY libraries/access-token-encryptor/ /overleaf/libraries/access-token-encryptor/
|
||||
COPY libraries/ai/ /overleaf/libraries/ai/
|
||||
COPY libraries/eslint-plugin/ /overleaf/libraries/eslint-plugin/
|
||||
COPY libraries/fetch-utils/ /overleaf/libraries/fetch-utils/
|
||||
COPY libraries/logger/ /overleaf/libraries/logger/
|
||||
@@ -97,7 +95,6 @@ RUN nice find /overleaf/services/web/public -name '*.js.map' -delete
|
||||
# copy source code and precompile pug images
|
||||
FROM deps-prod AS pug
|
||||
COPY libraries/access-token-encryptor/ /overleaf/libraries/access-token-encryptor/
|
||||
COPY libraries/ai/ /overleaf/libraries/ai/
|
||||
COPY libraries/eslint-plugin/ /overleaf/libraries/eslint-plugin/
|
||||
COPY libraries/fetch-utils/ /overleaf/libraries/fetch-utils/
|
||||
COPY libraries/logger/ /overleaf/libraries/logger/
|
||||
|
||||
@@ -570,7 +570,6 @@ IMAGE_SCRATCH ?= $(IMAGE_REPO):do-not-use-this-tag-for-deploys--it-is-used-for-e
|
||||
IMAGE_CACHE ?= $(IMAGE_REPO):cache-$(shell cat \
|
||||
$(MONOREPO)/package.json \
|
||||
$(MONOREPO)/package-lock.json \
|
||||
$(MONOREPO)/libraries/ai/package.json \
|
||||
$(MONOREPO)/libraries/access-token-encryptor/package.json \
|
||||
$(MONOREPO)/libraries/eslint-plugin/package.json \
|
||||
$(MONOREPO)/libraries/fetch-utils/package.json \
|
||||
|
||||
BIN
Binary file not shown.
@@ -37,6 +37,7 @@ export default /** @type {const} */ ([
|
||||
'integration_instructions',
|
||||
'lightbulb',
|
||||
'more_vert',
|
||||
'neurology',
|
||||
'note_add',
|
||||
'open_in_new',
|
||||
'password',
|
||||
|
||||
@@ -55,7 +55,7 @@ export type EditorManager = {
|
||||
getCurrentDocumentId: () => DocId | null
|
||||
setIgnoringExternalUpdates: (value: boolean) => void
|
||||
openDocWithId: (docId: string, options?: OpenDocOptions) => void
|
||||
openDoc: (document: Doc, options?: OpenDocOptions) => void
|
||||
openDoc: (document: Doc, options?: OpenDocOptions) => Promise<Doc | undefined>
|
||||
openDocs: OpenDocuments
|
||||
openFileWithId: (fileId: string) => void
|
||||
openInitialDoc: (docId?: string) => void
|
||||
|
||||
@@ -30,6 +30,7 @@ import { UserFeaturesProvider } from '@/shared/context/user-features-context'
|
||||
import { UserSettingsProvider } from '@/shared/context/user-settings-context'
|
||||
import { IdeRedesignSwitcherProvider } from './ide-redesign-switcher-context'
|
||||
import { CommandRegistryProvider } from './command-registry-context'
|
||||
import { EditorSelectionProvider } from '@/shared/context/editor-selection-context'
|
||||
import importOverleafModules from '../../../../macros/import-overleaf-module.macro'
|
||||
|
||||
const rootContextProviders = importOverleafModules('rootContextProviders') as {
|
||||
@@ -74,6 +75,7 @@ export const ReactContextRoot: FC<
|
||||
IdeRedesignSwitcherProvider,
|
||||
CommandRegistryProvider,
|
||||
UserFeaturesProvider,
|
||||
EditorSelectionProvider,
|
||||
...providers,
|
||||
}
|
||||
|
||||
@@ -121,9 +123,11 @@ export const ReactContextRoot: FC<
|
||||
<Providers.OutlineProvider>
|
||||
<Providers.IdeRedesignSwitcherProvider>
|
||||
<Providers.CommandRegistryProvider>
|
||||
{
|
||||
childrenWrappedWithDynamicProviders
|
||||
}
|
||||
<Providers.EditorSelectionProvider>
|
||||
{
|
||||
childrenWrappedWithDynamicProviders
|
||||
}
|
||||
</Providers.EditorSelectionProvider>
|
||||
</Providers.CommandRegistryProvider>
|
||||
</Providers.IdeRedesignSwitcherProvider>
|
||||
</Providers.OutlineProvider>
|
||||
|
||||
@@ -54,6 +54,7 @@ import { historyOT } from './history-ot'
|
||||
import { trackDetachedComments } from './track-detached-comments'
|
||||
import { reviewTooltip } from './review-tooltip'
|
||||
import { tooltipsReposition } from './tooltips-reposition'
|
||||
import { selectionListener } from '@/features/source-editor/extensions/selection-listener'
|
||||
|
||||
const moduleExtensions: Array<(options: Record<string, any>) => Extension> =
|
||||
importOverleafModules('sourceEditorExtensions').map(
|
||||
@@ -172,4 +173,5 @@ export const createExtensions = (options: Record<string, any>): Extension[] => [
|
||||
geometryChangeEvent(),
|
||||
fileTreeItemDrop(),
|
||||
tooltipsReposition(),
|
||||
selectionListener(options.setEditorSelection),
|
||||
]
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { ViewPlugin } from '@codemirror/view'
|
||||
import { EditorSelection } from '@codemirror/state'
|
||||
import { debounce } from 'lodash'
|
||||
|
||||
export const selectionListener = (
|
||||
setEditorSelection: (value: EditorSelection | undefined) => void
|
||||
) => {
|
||||
const debouncedSetEditorSelection = debounce(setEditorSelection, 250)
|
||||
|
||||
return ViewPlugin.define(() => {
|
||||
return {
|
||||
update(update) {
|
||||
if (update.selectionSet) {
|
||||
debouncedSetEditorSelection(update.state.selection)
|
||||
}
|
||||
},
|
||||
destroy() {
|
||||
setEditorSelection(undefined)
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -60,6 +60,7 @@ import { useEditorPropertiesContext } from '@/features/ide-react/context/editor-
|
||||
import { SearchQuery } from '@codemirror/search'
|
||||
import { beforeChangeDocEffect } from '@/features/source-editor/extensions/before-change-doc'
|
||||
import { useActiveOverallTheme } from '@/shared/hooks/use-active-overall-theme'
|
||||
import { useEditorSelectionContext } from '@/shared/context/editor-selection-context'
|
||||
|
||||
function useCodeMirrorScope(view: EditorView) {
|
||||
const { fileTreeData } = useFileTreeData()
|
||||
@@ -106,6 +107,8 @@ function useCodeMirrorScope(view: EditorView) {
|
||||
|
||||
const { referenceKeys, searchLocalReferences } = useReferencesContext()
|
||||
|
||||
const { setEditorSelection } = useEditorSelectionContext()
|
||||
|
||||
const ranges = useRangesContext()
|
||||
const threads = useThreadsContext()
|
||||
|
||||
@@ -335,6 +338,7 @@ function useCodeMirrorScope(view: EditorView) {
|
||||
initialSearchQuery: searchQueryRef.current,
|
||||
showBoundary,
|
||||
handleException,
|
||||
setEditorSelection,
|
||||
}),
|
||||
})
|
||||
view.setState(state)
|
||||
@@ -364,7 +368,7 @@ function useCodeMirrorScope(view: EditorView) {
|
||||
}
|
||||
// IMPORTANT: This effect must not depend on anything variable apart from currentDocument,
|
||||
// as the editor state is recreated when the effect runs.
|
||||
}, [view, currentDocument, showBoundary, handleException])
|
||||
}, [view, currentDocument, showBoundary, handleException, setEditorSelection])
|
||||
|
||||
useEffect(() => {
|
||||
if (openDocName) {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { ButtonProps } from './button-props'
|
||||
|
||||
type BaseIconButtonProps = ButtonProps & {
|
||||
accessibilityLabel?: string
|
||||
type?: 'button' | 'submit'
|
||||
type?: 'button' | 'submit' | 'reset'
|
||||
}
|
||||
|
||||
type FilledIconButtonProps = BaseIconButtonProps & {
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import {
|
||||
createContext,
|
||||
type Dispatch,
|
||||
type FC,
|
||||
type PropsWithChildren,
|
||||
type SetStateAction,
|
||||
useContext,
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react'
|
||||
import type { EditorSelection } from '@codemirror/state'
|
||||
|
||||
export const EditorSelectionContext = createContext<
|
||||
| {
|
||||
editorSelection: EditorSelection | undefined
|
||||
setEditorSelection: Dispatch<SetStateAction<EditorSelection | undefined>>
|
||||
}
|
||||
| undefined
|
||||
>(undefined)
|
||||
|
||||
export const EditorSelectionProvider: FC<PropsWithChildren> = ({
|
||||
children,
|
||||
}) => {
|
||||
const [editorSelection, setEditorSelection] = useState<EditorSelection>()
|
||||
|
||||
const value = useMemo(() => {
|
||||
return { editorSelection, setEditorSelection }
|
||||
}, [editorSelection])
|
||||
|
||||
return (
|
||||
<EditorSelectionContext.Provider value={value}>
|
||||
{children}
|
||||
</EditorSelectionContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useEditorSelectionContext = () => {
|
||||
const context = useContext(EditorSelectionContext)
|
||||
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
'useEditorSelectionContext is only available inside EditorSelectionProvider'
|
||||
)
|
||||
}
|
||||
|
||||
return context
|
||||
}
|
||||
@@ -81,8 +81,8 @@
|
||||
"safari > 14"
|
||||
],
|
||||
"dependencies": {
|
||||
"@ai-sdk/mcp": "^1.0.0-beta.13",
|
||||
"@ai-sdk/openai": "^3.0.0-beta.44",
|
||||
"@ai-sdk/mcp": "^1.0.0-beta.15",
|
||||
"@ai-sdk/openai": "^3.0.0-beta.59",
|
||||
"@aws-sdk/client-ses": "^3.864.0",
|
||||
"@contentful/rich-text-html-renderer": "^16.0.2",
|
||||
"@contentful/rich-text-types": "^16.0.2",
|
||||
@@ -109,7 +109,7 @@
|
||||
"@stripe/stripe-js": "^7.7.0",
|
||||
"@xmldom/xmldom": "^0.7.13",
|
||||
"accepts": "^1.3.7",
|
||||
"ai": "^6.0.0-beta.84",
|
||||
"ai": "^6.0.0-beta.99",
|
||||
"ajv": "^8.12.0",
|
||||
"archiver": "^5.3.0",
|
||||
"async": "^3.2.5",
|
||||
@@ -199,6 +199,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"5to6-codemod": "^1.8.0",
|
||||
"@ai-sdk/react": "^3.0.0-beta.99",
|
||||
"@babel/cli": "^7.27.0",
|
||||
"@babel/core": "^7.26.10",
|
||||
"@babel/plugin-proposal-decorators": "^7.27.0",
|
||||
@@ -221,7 +222,6 @@
|
||||
"@lezer/highlight": "^1.2.1",
|
||||
"@lezer/lr": "^1.4.2",
|
||||
"@lezer/markdown": "^1.4.3",
|
||||
"@overleaf/ai": "^1.0.0",
|
||||
"@overleaf/codemirror-tree-view": "^0.1.3",
|
||||
"@overleaf/dictionaries": "https://github.com/overleaf/dictionaries/archive/refs/tags/v0.0.3.tar.gz",
|
||||
"@overleaf/eslint-plugin": "*",
|
||||
@@ -258,6 +258,7 @@
|
||||
"@types/chai": "^4.3.0",
|
||||
"@types/dateformat": "^5.0.3",
|
||||
"@types/diff": "^5.2.3",
|
||||
"@types/dom-speech-recognition": "^0.0.7",
|
||||
"@types/events": "^3.0.3",
|
||||
"@types/express": "^4.17.23",
|
||||
"@types/mocha": "^9.1.0",
|
||||
@@ -345,6 +346,7 @@
|
||||
"jscodeshift": "^17.0.0",
|
||||
"jsdom": "^19.0.0",
|
||||
"jsdom-global": "^3.0.2",
|
||||
"katex": "^0.16.25",
|
||||
"knip": "^5.64.1",
|
||||
"match-sorter": "^6.2.0",
|
||||
"mathjax": "^3.2.2",
|
||||
@@ -378,10 +380,15 @@
|
||||
"react-google-recaptcha": "^3.1.0",
|
||||
"react-i18next": "^13.3.1",
|
||||
"react-linkify": "^1.0.0-alpha",
|
||||
"react-markdown": "^10.1.0",
|
||||
"react-refresh": "^0.14.0",
|
||||
"react-resizable-panels": "^2.1.1",
|
||||
"react-syntax-highlighter": "^15.6.6",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rehype-external-links": "^3.0.0",
|
||||
"rehype-katex": "^7.0.1",
|
||||
"rehype-sanitize": "^6.0.0",
|
||||
"remark-math": "^6.0.0",
|
||||
"resolve-url-loader": "^5.0.0",
|
||||
"samlp": "^7.0.2",
|
||||
"sandboxed-module": "overleaf/node-sandboxed-module#cafa2d60f17ce75cc023e6f296eb8de79d92d35d",
|
||||
@@ -401,6 +408,7 @@
|
||||
"ts-loader": "^9.5.2",
|
||||
"tty-browserify": "^0.0.1",
|
||||
"typescript": "^5.8.3",
|
||||
"use-stick-to-bottom": "^1.1.1",
|
||||
"uuid": "^9.0.1",
|
||||
"vitest": "^3.1.2",
|
||||
"w3c-keyname": "^2.2.8",
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
"@testing-library/cypress",
|
||||
"reflect-metadata",
|
||||
"vitest/globals",
|
||||
"@testing-library/jest-dom"
|
||||
"@testing-library/jest-dom",
|
||||
"@types/dom-speech-recognition"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
|
||||
@@ -10,7 +10,6 @@ const {
|
||||
|
||||
const PackageVersions = require('./app/src/infrastructure/PackageVersions.js')
|
||||
const invalidateBabelCacheIfNeeded = require('./frontend/macros/invalidate-babel-cache-if-needed')
|
||||
const { dirname } = require('node:path')
|
||||
|
||||
// Make sure that babel-macros are re-evaluated after changing the modules config
|
||||
invalidateBabelCacheIfNeeded()
|
||||
@@ -259,26 +258,6 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
// CSS from AI module
|
||||
include: dirname(require.resolve('@overleaf/ai')),
|
||||
use: [
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
exportType: 'css-style-sheet',
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
postcssOptions: {
|
||||
config: require.resolve('@overleaf/ai/postcss.config.js'),
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
// Standard CSS processing (extracted into separate file)
|
||||
use: [MiniCssExtractPlugin.loader, 'css-loader'],
|
||||
|
||||
Reference in New Issue
Block a user