diff --git a/services/web/frontend/js/features/source-editor/extensions/visual/atomic-decorations.ts b/services/web/frontend/js/features/source-editor/extensions/visual/atomic-decorations.ts index 29223434d5..7437bce8d6 100644 --- a/services/web/frontend/js/features/source-editor/extensions/visual/atomic-decorations.ts +++ b/services/web/frontend/js/features/source-editor/extensions/visual/atomic-decorations.ts @@ -24,6 +24,7 @@ import { EndWidget } from './visual-widgets/end' import { getEnvironmentArguments, getEnvironmentName, + getUnstarredEnvironmentName, parseFigureData, } from '../../utils/tree-operations/environments' import { MathWidget } from './visual-widgets/math' @@ -224,7 +225,7 @@ export const atomicDecorations = (options: Options) => { enter(nodeRef) { if (nodeRef.type.is('$Environment')) { if (shouldDecorate(state, nodeRef)) { - const envName = getEnvironmentName(nodeRef.node, state) + const envName = getUnstarredEnvironmentName(nodeRef.node, state) const hideInEnvironmentTypes = ['figure', 'table'] if (envName && hideInEnvironmentTypes.includes(envName)) { const beginNode = nodeRef.node.getChild('BeginEnv') diff --git a/services/web/frontend/js/features/source-editor/extensions/visual/mark-decorations.ts b/services/web/frontend/js/features/source-editor/extensions/visual/mark-decorations.ts index dce01251da..2bd42c6b17 100644 --- a/services/web/frontend/js/features/source-editor/extensions/visual/mark-decorations.ts +++ b/services/web/frontend/js/features/source-editor/extensions/visual/mark-decorations.ts @@ -6,7 +6,7 @@ import { } from '@codemirror/view' import { EditorState, Range } from '@codemirror/state' import { syntaxTree } from '@codemirror/language' -import { getEnvironmentName } from '../../utils/tree-operations/environments' +import { getUnstarredEnvironmentName } from '../../utils/tree-operations/environments' import { centeringNodeForEnvironment } from '../../utils/tree-operations/figure' import { Tree } from '@lezer/common' @@ -103,7 +103,10 @@ export const markDecorations = ViewPlugin.define( } } } else if (nodeRef.type.is('$Environment')) { - const environmentName = getEnvironmentName(nodeRef.node, state) + const environmentName = getUnstarredEnvironmentName( + nodeRef.node, + state + ) switch (environmentName) { case 'abstract': diff --git a/services/web/frontend/js/features/source-editor/lezer-latex/latex.grammar b/services/web/frontend/js/features/source-editor/lezer-latex/latex.grammar index 03c44b75e6..efb5e2587f 100644 --- a/services/web/frontend/js/features/source-editor/lezer-latex/latex.grammar +++ b/services/web/frontend/js/features/source-editor/lezer-latex/latex.grammar @@ -250,7 +250,7 @@ KnownCommand { IncludeGraphicsArgument { FilePathArgument } } | Caption { - CaptionCtrlSeq optionalWhitespace? OptionalArgument? TextArgument + CaptionCtrlSeq "*"? optionalWhitespace? OptionalArgument? TextArgument } | Label { LabelCtrlSeq optionalWhitespace? LabelArgument diff --git a/services/web/frontend/js/features/source-editor/lezer-latex/tokens.mjs b/services/web/frontend/js/features/source-editor/lezer-latex/tokens.mjs index 29674c79c6..ef72e98ee2 100644 --- a/services/web/frontend/js/features/source-editor/lezer-latex/tokens.mjs +++ b/services/web/frontend/js/features/source-editor/lezer-latex/tokens.mjs @@ -739,6 +739,7 @@ const otherKnownEnvNames = { document: DocumentEnvName, tikzpicture: TikzPictureEnvName, figure: FigureEnvName, + 'figure*': FigureEnvName, subfigure: FigureEnvName, enumerate: ListEnvName, itemize: ListEnvName, diff --git a/services/web/frontend/js/features/source-editor/utils/tree-operations/environments.ts b/services/web/frontend/js/features/source-editor/utils/tree-operations/environments.ts index 7087486fd5..fe754ff66c 100644 --- a/services/web/frontend/js/features/source-editor/utils/tree-operations/environments.ts +++ b/services/web/frontend/js/features/source-editor/utils/tree-operations/environments.ts @@ -236,6 +236,11 @@ export function getEnvironmentName( return state.sliceDoc(nameNode.from, nameNode.to) } +export const getUnstarredEnvironmentName = ( + node: SyntaxNode | null, + state: EditorState +): string | undefined => getEnvironmentName(node, state)?.replace(/\*$/, '') + export function getEnvironmentArguments(environmentNode: SyntaxNode) { return environmentNode.getChild('BeginEnv')?.getChildren('TextArgument') } diff --git a/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-floats.spec.tsx b/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-floats.spec.tsx new file mode 100644 index 0000000000..0ac5428967 --- /dev/null +++ b/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-floats.spec.tsx @@ -0,0 +1,72 @@ +import { FC } from 'react' +import { EditorProviders } from '../../../helpers/editor-providers' +import CodemirrorEditor from '../../../../../frontend/js/features/source-editor/components/codemirror-editor' +import { mockScope } from '../helpers/mock-scope' + +const Container: FC = ({ children }) => ( +