mirror of
https://github.com/overleaf/overleaf.git
synced 2024-12-10 14:06:21 -05:00
7f37ba737c
* Update Copybara options in preparation for open-sourcing the source editor * Move files * Update paths * Remove source-editor module and checks for its existence * Explicitly mention CM6 license in files that contain code adapted from CM6 GitOrigin-RevId: 89b7cc2b409db01ad103198ccbd1b126ab56349b
169 lines
5.3 KiB
TypeScript
169 lines
5.3 KiB
TypeScript
import { foldEffect, foldState } from '@codemirror/language'
|
|
import { EditorSelection, EditorState } from '@codemirror/state'
|
|
import { DecorationSet, EditorView } from '@codemirror/view'
|
|
import { expect } from 'chai'
|
|
import { duplicateSelection } from '../../../../../frontend/js/features/source-editor/commands/ranges'
|
|
|
|
type Position = {
|
|
from: number
|
|
to: number
|
|
}
|
|
|
|
function folds(foldRanges: DecorationSet) {
|
|
const ranges: Position[] = []
|
|
foldRanges.between(Number.MIN_VALUE, Number.MAX_VALUE, (from, to) => {
|
|
ranges.push({ from, to })
|
|
})
|
|
return ranges
|
|
}
|
|
|
|
describe('Line duplication command', function () {
|
|
describe('For single selections', function () {
|
|
describe('For cursor selection', function () {
|
|
it('Cursor selection duplicates line downwards', function () {
|
|
const view = new EditorView({
|
|
doc: 'line1\nline2',
|
|
selection: EditorSelection.cursor(0),
|
|
})
|
|
|
|
duplicateSelection(view)
|
|
|
|
expect(view.state.doc.toString()).to.equal('line1\nline1\nline2')
|
|
|
|
expect(view.state.selection.ranges.length).to.equal(1)
|
|
expect(view.state.selection.ranges[0].eq(EditorSelection.cursor(0))).to
|
|
.be.true
|
|
})
|
|
|
|
it('Preserves folded ranges', function () {
|
|
const view = new EditorView({
|
|
doc: '\\begin{itemize}\n\t\\item test\n\\end{itemize}',
|
|
extensions: foldState,
|
|
})
|
|
|
|
view.dispatch(
|
|
view.state.update({
|
|
selection: EditorSelection.cursor(0),
|
|
// Fold to \begin{itemize}...\end{itemize}
|
|
effects: [foldEffect.of({ from: 15, to: 28 })],
|
|
})
|
|
)
|
|
|
|
duplicateSelection(view)
|
|
|
|
expect(folds(view.state.field(foldState))).to.deep.equal([
|
|
{ from: 15, to: 28 },
|
|
{ from: 57, to: 70 },
|
|
])
|
|
|
|
expect(view.state.selection.ranges.length).to.equal(1)
|
|
expect(view.state.selection.ranges[0].eq(EditorSelection.cursor(0))).to
|
|
.be.true
|
|
})
|
|
})
|
|
describe('For range selections', function () {
|
|
it('Duplicates line with a cursor downwards', function () {
|
|
const view = new EditorView({
|
|
doc: 'line1\nline2',
|
|
selection: EditorSelection.cursor(0),
|
|
})
|
|
|
|
duplicateSelection(view)
|
|
|
|
expect(view.state.doc.toString()).to.equal('line1\nline1\nline2')
|
|
})
|
|
|
|
it('Duplicates range forwards', function () {
|
|
const view = new EditorView({
|
|
doc: 'line1\nline2',
|
|
selection: EditorSelection.range(0, 5),
|
|
})
|
|
|
|
duplicateSelection(view)
|
|
|
|
expect(view.state.doc.toString()).to.equal('line1line1\nline2')
|
|
expect(view.state.selection.ranges.length).to.equal(1)
|
|
expect(view.state.selection.ranges[0].eq(EditorSelection.range(5, 10)))
|
|
.to.be.true
|
|
})
|
|
|
|
it('Duplicates range backwards', function () {
|
|
const view = new EditorView({
|
|
doc: 'line1\nline2',
|
|
selection: EditorSelection.range(5, 0),
|
|
})
|
|
|
|
duplicateSelection(view)
|
|
|
|
expect(view.state.doc.toString()).to.equal('line1line1\nline2')
|
|
expect(view.state.selection.ranges.length).to.equal(1)
|
|
expect(view.state.selection.ranges[0].eq(EditorSelection.range(5, 0)))
|
|
.to.be.true
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('For multiple selections', function () {
|
|
it('Preserves folded ranges', function () {
|
|
const doc =
|
|
'\\begin{itemize}\n\t\\item line1\n\\end{itemize}\n\\begin{itemize}\n\t\\item line2\n\\end{itemize}'
|
|
const view = new EditorView({
|
|
doc,
|
|
extensions: [foldState, EditorState.allowMultipleSelections.of(true)],
|
|
})
|
|
|
|
view.dispatch(
|
|
view.state.update({
|
|
selection: EditorSelection.create([
|
|
EditorSelection.cursor(0),
|
|
EditorSelection.cursor(43),
|
|
]),
|
|
effects: [
|
|
foldEffect.of({ from: 15, to: 29 }),
|
|
foldEffect.of({ from: 58, to: 72 }),
|
|
],
|
|
})
|
|
)
|
|
|
|
duplicateSelection(view)
|
|
|
|
expect(view.state.doc.toString()).to.equal(
|
|
'\\begin{itemize}\n\t\\item line1\n\\end{itemize}\n\\begin{itemize}\n\t\\item line1\n\\end{itemize}\n\\begin{itemize}\n\t\\item line2\n\\end{itemize}\n\\begin{itemize}\n\t\\item line2\n\\end{itemize}'
|
|
)
|
|
|
|
expect(folds(view.state.field(foldState))).to.deep.equal([
|
|
{ from: 15, to: 29 },
|
|
{ from: 58, to: 72 },
|
|
{ from: 101, to: 115 },
|
|
{ from: 144, to: 158 },
|
|
])
|
|
|
|
expect(view.state.selection.ranges.length).to.equal(2)
|
|
expect(view.state.selection.ranges[0].eq(EditorSelection.cursor(0))).to.be
|
|
.true
|
|
expect(view.state.selection.ranges[1].eq(EditorSelection.cursor(86))).to
|
|
.be.true
|
|
})
|
|
|
|
it('Duplicates all selections', function () {
|
|
const view = new EditorView({
|
|
doc: 'line1\nline2',
|
|
extensions: [EditorState.allowMultipleSelections.of(true)],
|
|
selection: EditorSelection.create([
|
|
EditorSelection.cursor(1),
|
|
EditorSelection.range(7, 9),
|
|
]),
|
|
})
|
|
|
|
duplicateSelection(view)
|
|
|
|
expect(view.state.doc.toString()).to.equal('line1\nline1\nlinine2')
|
|
|
|
expect(view.state.selection.ranges.length).to.equal(2)
|
|
expect(view.state.selection.ranges[0].eq(EditorSelection.cursor(1))).to.be
|
|
.true
|
|
expect(view.state.selection.ranges[1].eq(EditorSelection.range(15, 17)))
|
|
.to.be.true
|
|
})
|
|
})
|
|
})
|