mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -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
74 lines
2 KiB
TypeScript
74 lines
2 KiB
TypeScript
import { ChangeSet, StateField } from '@codemirror/state'
|
|
import {
|
|
ProjectionItem,
|
|
ProjectionResult,
|
|
getUpdatedProjection,
|
|
EnterNodeFn,
|
|
ProjectionStatus,
|
|
} from './tree-operations/projection'
|
|
|
|
export function mergeChangeRanges(changes: ChangeSet) {
|
|
let fromA = Number.MAX_VALUE
|
|
let fromB = Number.MAX_VALUE
|
|
let toA = Number.MIN_VALUE
|
|
let toB = Number.MIN_VALUE
|
|
changes.iterChangedRanges(
|
|
(changeFromA, changeToA, changeFromB, changeToB) => {
|
|
fromA = Math.min(changeFromA, fromA)
|
|
fromB = Math.min(changeFromB, fromB)
|
|
toA = Math.max(changeToA, toA)
|
|
toB = Math.max(changeToB, toB)
|
|
}
|
|
)
|
|
return { fromA, toA, fromB, toB }
|
|
}
|
|
|
|
/**
|
|
* Creates a StateField to manage a 'projection' of the document. Type T is the subclass of
|
|
* ProjectionItem that we will extract from the document.
|
|
*
|
|
* @param enterNode A function to call when 'enter'ing a node while traversing the syntax tree,
|
|
* Used to identify nodes we are interested in, and create instances of T.
|
|
*/
|
|
export function makeProjectionStateField<T extends ProjectionItem>(
|
|
enterNode: EnterNodeFn<T>
|
|
): StateField<ProjectionResult<T>> {
|
|
const field = StateField.define<ProjectionResult<T>>({
|
|
create(state) {
|
|
const projection = getUpdatedProjection<T>(
|
|
state,
|
|
0,
|
|
state.doc.length,
|
|
0,
|
|
state.doc.length,
|
|
true,
|
|
enterNode
|
|
)
|
|
return projection
|
|
},
|
|
update(currentProjection, transaction) {
|
|
if (
|
|
transaction.docChanged ||
|
|
currentProjection.status !== ProjectionStatus.Complete
|
|
) {
|
|
const { fromA, toA, fromB, toB } = mergeChangeRanges(
|
|
transaction.changes
|
|
)
|
|
const list = getUpdatedProjection<T>(
|
|
transaction.state,
|
|
fromA,
|
|
toA,
|
|
fromB,
|
|
toB,
|
|
false,
|
|
enterNode,
|
|
transaction,
|
|
currentProjection
|
|
)
|
|
return list
|
|
}
|
|
return currentProjection
|
|
},
|
|
})
|
|
return field
|
|
}
|