From 787c3fb55445334b684fe42a9cabd3c67ee3b795 Mon Sep 17 00:00:00 2001 From: Andrew Rumble Date: Mon, 8 Apr 2024 15:58:28 +0100 Subject: [PATCH] Merge pull request #17786 from overleaf/ar-select-caption-in-inserted-figures Select caption text when new figure inserted GitOrigin-RevId: 443594ff03c5a5cd316623e60b231a6af4390d3c --- .../components/figure-modal/figure-modal.tsx | 42 ++++----- .../codemirror-editor-figure-modal.spec.tsx | 92 ++++++++++++++++++- 2 files changed, 107 insertions(+), 27 deletions(-) diff --git a/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal.tsx b/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal.tsx index d77cdf3db9..0b0674d823 100644 --- a/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal.tsx +++ b/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal.tsx @@ -10,6 +10,7 @@ import { FigureModalFooter } from './figure-modal-footer' import { lazy, memo, Suspense, useCallback, useEffect } from 'react' import { useCodeMirrorViewContext } from '../codemirror-editor' import { ChangeSpec } from '@codemirror/state' +import { snippet } from '@codemirror/autocomplete' import { FigureData, PastedImageData, @@ -206,29 +207,26 @@ const FigureModalContent = () => { effects: editFigureDataEffect.of(null), }) } else { - view.dispatch( - view.state.changeByRange(range => { - const { pos, suffix } = ensureEmptyLine(view.state, range) - const widthArgument = - width !== undefined ? `[width=${width}\\linewidth]` : '' - const changes: ChangeSpec = view.state.changes({ - insert: prepareLines( - [ - '\\begin{figure}', - '\t\\centering', - `\t\\includegraphics${widthArgument}{${path}}`, - `\t${captionCommand}`, - `\t${labelCommand}`, - `\\end{figure}${suffix}`, - ], - view.state, - pos - ), - from: pos, - }) + const { pos, suffix } = ensureEmptyLine( + view.state, + view.state.selection.main + ) - return { range: range.map(changes), changes } - }) + const widthArgument = + width !== undefined ? `[width=${width}\\linewidth]` : '' + const caption = includeCaption ? `\n\t\\caption{\${Enter Caption}}` : '' + const label = includeLabel ? `\n\t\\label{\${fig:enter-label}}` : '' + + snippet( + `\\begin{figure} +\t\\centering +\t\\includegraphics${widthArgument}{${path}}${caption}${label} +\\end{figure}${suffix}\${}` + )( + { state: view.state, dispatch: view.dispatch }, + { label: 'figure' }, + pos, + pos ) } hide() diff --git a/services/web/test/frontend/features/source-editor/components/codemirror-editor-figure-modal.spec.tsx b/services/web/test/frontend/features/source-editor/components/codemirror-editor-figure-modal.spec.tsx index 8d0696aab3..122acc22d0 100644 --- a/services/web/test/frontend/features/source-editor/components/codemirror-editor-figure-modal.spec.tsx +++ b/services/web/test/frontend/features/source-editor/components/codemirror-editor-figure-modal.spec.tsx @@ -113,7 +113,7 @@ describe('', function () { cy.get('.cm-content').should( 'have.text', - '\\begin{figure} \\centering Enter Caption 🏷fig:enter-label\\end{figure}' + '\\begin{figure} \\centering \\caption{Enter Caption} 🏷fig:enter-label\\end{figure}' ) }) @@ -159,7 +159,7 @@ describe('', function () { cy.findByText('Insert figure').click() cy.get('.cm-content').should( 'have.text', - '\\begin{figure} \\centering Enter Caption 🏷fig:enter-label\\end{figure}' + '\\begin{figure} \\centering \\caption{Enter Caption} 🏷fig:enter-label\\end{figure}' ) }) }) @@ -233,7 +233,7 @@ describe('', function () { cy.get('.cm-content').should( 'have.text', - '\\begin{figure} \\centering Enter Caption 🏷fig:enter-label\\end{figure}' + '\\begin{figure} \\centering \\caption{Enter Caption} 🏷fig:enter-label\\end{figure}' ) }) @@ -261,7 +261,7 @@ describe('', function () { cy.get('.cm-content').should( 'have.text', - '\\begin{figure} \\centering Enter Caption 🏷fig:enter-label\\end{figure}' + '\\begin{figure} \\centering \\caption{Enter Caption} 🏷fig:enter-label\\end{figure}' ) }) }) @@ -403,7 +403,89 @@ describe('', function () { cy.get('.cm-content').should( 'have.text', - '\\begin{figure} \\centering Enter Caption 🏷fig:enter-label\\end{figure}' + '\\begin{figure} \\centering \\caption{Enter Caption} 🏷fig:enter-label\\end{figure}' + ) + }) + + it('Selects the caption when the figure is inserted with a caption', function () { + cy.get('@image-url-input').type('https://my-fake-website.com/frog.jpg') + cy.findByText('Insert figure').click() + + cy.get('@linked-file-request').should('have.been.calledWithMatch', { + body: { + provider: 'url', + data: { + url: 'https://my-fake-website.com/frog.jpg', + }, + }, + }) + + cy.get('.cm-selectionLayer .cm-selectionBackground').should( + 'have.length', + 1 + ) + + // If caption is selected then typing will replace the whole caption + cy.focused().type('My caption') + cy.get('.cm-content').should( + 'have.text', + '\\begin{figure} \\centering \\caption{My caption} 🏷fig:enter-label\\end{figure}' + ) + }) + + it('Selects the label when the figure is inserted without a caption', function () { + cy.get('@image-url-input').type('https://my-fake-website.com/frog.jpg') + cy.get('@include-caption-checkbox').uncheck() + cy.findByText('Insert figure').click() + + cy.get('@linked-file-request').should('have.been.calledWithMatch', { + body: { + provider: 'url', + data: { + url: 'https://my-fake-website.com/frog.jpg', + }, + }, + }) + + cy.get('.cm-selectionLayer .cm-selectionBackground').should( + 'have.length', + 1 + ) + + // If label is selected then typing will replace the whole label + cy.focused().type('fig:my-label') + cy.get('.cm-content').should( + 'have.text', + '\\begin{figure} \\centering \\label{fig:my-label}\\end{figure}' + ) + }) + + it('Places the cursor after the figure if it is inserted without a caption or a label', function () { + cy.get('@image-url-input').type('https://my-fake-website.com/frog.jpg') + cy.get('@include-caption-checkbox').uncheck() + cy.get('@include-label-checkbox').uncheck() + + cy.findByText('Insert figure').click() + + cy.get('@linked-file-request').should('have.been.calledWithMatch', { + body: { + provider: 'url', + data: { + url: 'https://my-fake-website.com/frog.jpg', + }, + }, + }) + + cy.get('.cm-content').should( + 'have.text', + '\\begin{figure} \\centering\\end{figure}' + ) + + cy.focused().type('Some more text') + + cy.get('.cm-content').should( + 'have.text', + '\\begin{figure} \\centering\\end{figure}Some more text' ) }) })