mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-06-10 22:50:46 +02:00
Only select content when opening a file if it matches the expected text (#23324)
GitOrigin-RevId: 8b180ab897bb9027743c37f2b7faf690b7177eb6
This commit is contained in:
@@ -0,0 +1 @@
|
||||
Simply use the section and subsection commands, as in this example document! With Overleaf, all the formatting and numbering is handled automatically according to the template you've chosen. If you're using the Visual Editor, you can also create new section and subsections via the buttons in the editor toolbar.
|
||||
@@ -0,0 +1,8 @@
|
||||
@article{greenwade93,
|
||||
author = "George D. Greenwade",
|
||||
title = "The {C}omprehensive {T}ex {A}rchive {N}etwork ({CTAN})",
|
||||
year = "1993",
|
||||
journal = "TUGBoat",
|
||||
volume = "14",
|
||||
number = "3",
|
||||
pages = "342--351"}
|
||||
@@ -1,6 +1,6 @@
|
||||
export interface GotoLineOptions {
|
||||
gotoLine: number
|
||||
gotoColumn?: number
|
||||
selectionLength?: number
|
||||
selectText?: string
|
||||
syncToPdf?: boolean
|
||||
}
|
||||
|
||||
@@ -131,20 +131,32 @@ const dispatchSelectionAndScroll = (
|
||||
})
|
||||
}
|
||||
|
||||
const selectTextIfExists = (doc: Text, pos: number, selectText: string) => {
|
||||
const selectionLength = pos + selectText.length
|
||||
const text = doc.sliceString(pos, selectionLength)
|
||||
return text === selectText
|
||||
? EditorSelection.range(pos, selectionLength)
|
||||
: EditorSelection.cursor(doc.lineAt(pos).from)
|
||||
}
|
||||
|
||||
export const setCursorLineAndScroll = (
|
||||
view: EditorView,
|
||||
lineNumber: number,
|
||||
columnNumber = 0,
|
||||
selectionLength?: number
|
||||
selectText?: string
|
||||
) => {
|
||||
// TODO: map the position through any changes since the previous compile?
|
||||
|
||||
let selectionRange
|
||||
try {
|
||||
const pos = findValidPosition(view.state.doc, lineNumber, columnNumber)
|
||||
selectionRange = selectionLength
|
||||
? EditorSelection.range(pos, pos + selectionLength)
|
||||
: EditorSelection.cursor(pos)
|
||||
const { doc } = view.state
|
||||
const pos = findValidPosition(doc, lineNumber, columnNumber)
|
||||
dispatchSelectionAndScroll(
|
||||
view,
|
||||
selectText
|
||||
? selectTextIfExists(doc, pos, selectText)
|
||||
: EditorSelection.cursor(pos)
|
||||
)
|
||||
} catch (error) {
|
||||
// ignore invalid cursor position
|
||||
debugConsole.debug('invalid cursor position', error)
|
||||
|
||||
@@ -476,7 +476,7 @@ function useCodeMirrorScope(view: EditorView) {
|
||||
view,
|
||||
options.gotoLine,
|
||||
options.gotoColumn,
|
||||
options.selectionLength
|
||||
options.selectText
|
||||
)
|
||||
if (options.syncToPdf) {
|
||||
emitSyncToPdf()
|
||||
|
||||
@@ -24,7 +24,7 @@ import { isMac } from '@/shared/utils/os'
|
||||
export type IdeLayout = 'sideBySide' | 'flat'
|
||||
export type IdeView = 'editor' | 'file' | 'pdf' | 'history'
|
||||
|
||||
type LayoutContextValue = {
|
||||
export type LayoutContextValue = {
|
||||
reattach: () => void
|
||||
detach: () => void
|
||||
detachIsLinked: boolean
|
||||
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
import '../../../helpers/bootstrap-5'
|
||||
import { EditorProviders } from '../../../helpers/editor-providers'
|
||||
import FullProjectSearch from '../../../../../modules/full-project-search/frontend/js/components/full-project-search'
|
||||
import {
|
||||
LayoutContext,
|
||||
LayoutContextValue,
|
||||
} from '@/shared/context/layout-context'
|
||||
import { FC, useState } from 'react'
|
||||
|
||||
describe('<FullProjectSearch/>', function () {
|
||||
beforeEach(function () {
|
||||
cy.interceptCompile()
|
||||
|
||||
cy.intercept('/project/*/flush', {
|
||||
statusCode: 204,
|
||||
}).as('project-history-flush')
|
||||
|
||||
cy.intercept('/project/*/changes?*', {
|
||||
body: [],
|
||||
}).as('project-history-changes')
|
||||
|
||||
cy.intercept('/project/*/latest/history', {
|
||||
body: { chunk: mockHistoryChunk },
|
||||
}).as('project-history-snapshot')
|
||||
|
||||
cy.intercept('get', '/project/*/blob/*', req => {
|
||||
const blobId = req.url.split('/').pop() as string
|
||||
|
||||
req.reply({
|
||||
fixture: `blobs/${blobId}`,
|
||||
})
|
||||
}).as('project-history-blob')
|
||||
})
|
||||
|
||||
it('displays the search form', function () {
|
||||
cy.mount(
|
||||
<EditorProviders providers={{ LayoutProvider }}>
|
||||
<FullProjectSearch />
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
cy.findByRole('button', { name: 'Search' })
|
||||
})
|
||||
|
||||
it('displays a close button', function () {
|
||||
cy.mount(
|
||||
<EditorProviders providers={{ LayoutProvider }}>
|
||||
<FullProjectSearch />
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
cy.findByRole('button', { name: 'Close' })
|
||||
})
|
||||
|
||||
it('displays matched content', function () {
|
||||
cy.mount(
|
||||
<EditorProviders providers={{ LayoutProvider }}>
|
||||
<FullProjectSearch />
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
cy.findByRole('searchbox', { name: 'Search' }).type('and{enter}')
|
||||
|
||||
cy.findByRole('button', { name: 'main.tex 5' }) // TODO: remove count from name?
|
||||
|
||||
cy.get('.matched-file-hit').as('matches')
|
||||
cy.get('@matches').should('have.length', 5)
|
||||
|
||||
cy.get('@matches').first().click()
|
||||
cy.get('@matches').first().should('have.class', 'matched-file-hit-selected')
|
||||
})
|
||||
})
|
||||
|
||||
const createInitialValue = () =>
|
||||
({
|
||||
reattach: cy.stub(),
|
||||
detach: cy.stub(),
|
||||
detachIsLinked: false,
|
||||
detachRole: null,
|
||||
changeLayout: cy.stub(),
|
||||
view: 'editor',
|
||||
setView: cy.stub(),
|
||||
chatIsOpen: false,
|
||||
setChatIsOpen: cy.stub(),
|
||||
reviewPanelOpen: false,
|
||||
setReviewPanelOpen: cy.stub(),
|
||||
miniReviewPanelVisible: false,
|
||||
setMiniReviewPanelVisible: cy.stub(),
|
||||
leftMenuShown: false,
|
||||
setLeftMenuShown: cy.stub(),
|
||||
loadingStyleSheet: false,
|
||||
setLoadingStyleSheet: cy.stub(),
|
||||
pdfLayout: 'flat',
|
||||
pdfPreviewOpen: false,
|
||||
projectSearchIsOpen: true,
|
||||
setProjectSearchIsOpen: cy.stub(),
|
||||
}) satisfies LayoutContextValue
|
||||
|
||||
const LayoutProvider: FC = ({ children }) => {
|
||||
const [value] = useState(createInitialValue)
|
||||
|
||||
return (
|
||||
<LayoutContext.Provider value={value}>{children}</LayoutContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
const mockHistoryChunk = {
|
||||
history: {
|
||||
snapshot: {
|
||||
files: {},
|
||||
},
|
||||
changes: [
|
||||
{
|
||||
operations: [
|
||||
{
|
||||
pathname: 'main.tex',
|
||||
file: {
|
||||
hash: '5199b66d9d1226551be436c66bad9d962cc05537',
|
||||
stringLength: 7066,
|
||||
},
|
||||
},
|
||||
],
|
||||
timestamp: '2025-01-03T10:10:40.840Z',
|
||||
authors: [],
|
||||
v2Authors: ['66e040e0da7136ec75ffe8a3'],
|
||||
projectVersion: '1.0',
|
||||
},
|
||||
{
|
||||
operations: [
|
||||
{
|
||||
pathname: 'sample.bib',
|
||||
file: {
|
||||
hash: 'a0e21c740cf81e868f158e30e88985b5ea1d6c19',
|
||||
stringLength: 244,
|
||||
},
|
||||
},
|
||||
],
|
||||
timestamp: '2025-01-03T10:10:40.856Z',
|
||||
authors: [],
|
||||
v2Authors: ['66e040e0da7136ec75ffe8a3'],
|
||||
projectVersion: '2.0',
|
||||
},
|
||||
{
|
||||
operations: [
|
||||
{
|
||||
pathname: 'frog.jpg',
|
||||
file: {
|
||||
hash: '5b889ef3cf71c83a4c027c4e4dc3d1a106b27809',
|
||||
byteLength: 97080,
|
||||
},
|
||||
},
|
||||
],
|
||||
timestamp: '2025-01-03T10:10:40.890Z',
|
||||
authors: [],
|
||||
v2Authors: ['66e040e0da7136ec75ffe8a3'],
|
||||
projectVersion: '3.0',
|
||||
},
|
||||
],
|
||||
},
|
||||
startVersion: 0,
|
||||
}
|
||||
Reference in New Issue
Block a user