[web] add BibTeX visual editor module (#30726)

* [web] add BibTeX visual editor module

* Make the visual editor hook open to extension

Instead of looking specifically for the bibtex visual editor, allow any
extension to provide a visual editor.

* Fix stylelint error

---------

Co-authored-by: Eric Mc Sween <5454374+emcsween@users.noreply.github.com>
GitOrigin-RevId: c85c27a2b119c826e3d00cbd475a2a21f1508091
This commit is contained in:
Domagoj Kriskovic
2026-01-14 12:41:41 +01:00
committed by Copybot
parent 64da16f0d1
commit 4e2ea44b61
6 changed files with 50 additions and 4 deletions

View File

@@ -432,6 +432,7 @@ const _ProjectController = {
}
const splitTests = [
'bibtex-visual-editor',
'compile-log-events',
'visual-preview',
'external-socket-heartbeat',

View File

@@ -1015,6 +1015,7 @@ module.exports = {
ssoCertificateInfo: [],
v1ImportDataScreen: [],
snapshotUtils: [],
visualEditorProviders: [],
usGovBanner: [],
rollingBuildsUpdatedAlert: [],
offlineModeToolbarButtons: [],

View File

@@ -17,9 +17,12 @@ import {
CodeMirrorViewContext,
} from './codemirror-context'
import MathPreviewTooltip from './math-preview-tooltip'
import { getVisualEditorComponent } from '../utils/visual-editor'
import { useToolbarMenuBarEditorCommands } from '@/features/ide-redesign/hooks/use-toolbar-menu-editor-commands'
import { useProjectContext } from '@/shared/context/project-context'
import { useFeatureFlag } from '@/shared/context/split-test-context'
import { useEditorOpenDocContext } from '@/features/ide-react/context/editor-open-doc-context'
import { useEditorPropertiesContext } from '@/features/ide-react/context/editor-properties-context'
// TODO: remove this when definitely no longer used
export * from './codemirror-context'
@@ -69,6 +72,13 @@ function CodeMirrorEditor() {
function CodeMirrorEditorComponents() {
useToolbarMenuBarEditorCommands()
const { features } = useProjectContext()
const { openDocName } = useEditorOpenDocContext()
const { showVisual } = useEditorPropertiesContext()
const VisualEditor =
showVisual && openDocName != null
? getVisualEditorComponent(openDocName)
: null
return (
<ReviewPanelProviders>
@@ -88,6 +98,8 @@ function CodeMirrorEditorComponents() {
<Component key={path} />
)
)}
{VisualEditor && <VisualEditor />}
</ReviewPanelProviders>
)
}

View File

@@ -1,10 +1,10 @@
import { ChangeEvent, FC, memo, useCallback } from 'react'
import OLTooltip from '@/shared/components/ol/ol-tooltip'
import { sendMB } from '../../../infrastructure/event-tracking'
import { isValidTeXFile } from '../../../main/is-valid-tex-file'
import { useTranslation } from 'react-i18next'
import { useEditorOpenDocContext } from '@/features/ide-react/context/editor-open-doc-context'
import { useEditorPropertiesContext } from '@/features/ide-react/context/editor-properties-context'
import { isVisualEditorAvailable } from '../utils/visual-editor'
function EditorSwitch() {
const { t } = useTranslation()
@@ -12,7 +12,9 @@ function EditorSwitch() {
useEditorPropertiesContext()
const { openDocName } = useEditorOpenDocContext()
const richTextAvailable = openDocName ? isValidTeXFile(openDocName) : false
const richTextAvailable = openDocName
? isVisualEditorAvailable(openDocName)
: false
const handleChange = useCallback(
(event: ChangeEvent<HTMLInputElement>) => {

View File

@@ -37,7 +37,6 @@ import { setVisual } from '../extensions/visual/visual'
import { useFileTreePathContext } from '@/features/file-tree/contexts/file-tree-path'
import { useUserSettingsContext } from '@/shared/context/user-settings-context'
import { setDocName } from '@/features/source-editor/extensions/doc-name'
import { isValidTeXFile } from '@/main/is-valid-tex-file'
import { captureException } from '@/infrastructure/error-reporter'
import grammarlyExtensionPresent from '@/shared/utils/grammarly'
import { debugConsole } from '@/utils/debugging'
@@ -62,6 +61,7 @@ import { beforeChangeDocEffect } from '@/features/source-editor/extensions/befor
import { useActiveOverallTheme } from '@/shared/hooks/use-active-overall-theme'
import { useEditorSelectionContext } from '@/shared/context/editor-selection-context'
import { useActiveEditorTheme } from '@/shared/hooks/use-active-editor-theme'
import { isVisualEditorAvailable } from '../utils/visual-editor'
function useCodeMirrorScope(view: EditorView) {
const { fileTreeData } = useFileTreeData()
@@ -273,7 +273,8 @@ function useCodeMirrorScope(view: EditorView) {
const { previewByPath } = useFileTreePathContext()
const showVisual = visual && !!openDocName && isValidTeXFile(openDocName)
const showVisual =
visual && !!openDocName && isVisualEditorAvailable(openDocName)
const visualRef = useRef({
previewByPath,

View File

@@ -0,0 +1,29 @@
import importOverleafModules from '../../../../macros/import-overleaf-module.macro'
import { isValidTeXFile } from '../../../main/is-valid-tex-file'
const visualEditorProviders = importOverleafModules('visualEditorProviders')
export function isVisualEditorAvailable(filename: string): boolean {
// Core LaTeX visual editor
if (isValidTeXFile(filename)) {
return true
}
// Visual editors provided by modules
for (const provider of visualEditorProviders) {
if (provider.import.isVisualEditorAvailable(filename)) {
return true
}
}
return false
}
export function getVisualEditorComponent(filename: string) {
for (const provider of visualEditorProviders) {
const component = provider.import.getVisualEditorComponent(filename)
if (component != null) {
return component
}
}
return null
}