Skip to content

Commit 3d540f4

Browse files
author
Loïc Mangeonjean
committed
feat!: switch from decoration ids to decoration filter
and make tools more robust
1 parent 8f4e492 commit 3d540f4

File tree

1 file changed

+54
-16
lines changed

1 file changed

+54
-16
lines changed

src/tools.ts

Lines changed: 54 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ function isPasteAction (handlerId: string, payload: unknown): payload is PastePa
1212
}
1313

1414
export function lockCodeWithoutDecoration (
15-
editor: monaco.editor.IStandaloneCodeEditor,
16-
decorations: string[],
15+
editor: monaco.editor.ICodeEditor,
16+
decorationFilter: (decoration: monaco.editor.IModelDecoration) => boolean,
1717
allowChangeFromSources: string[] = [],
1818
errorMessage?: string
1919
): monaco.IDisposable {
@@ -30,8 +30,14 @@ export function lockCodeWithoutDecoration (
3030
function canEditRange (range: monaco.IRange) {
3131
const model = editor.getModel()
3232
if (model != null) {
33-
const editableRanges = decorations.map(decoration => model.getDecorationRange(decoration))
34-
return editableRanges.some(editableRange => editableRange?.containsRange(range) ?? false)
33+
const editableRanges = model
34+
.getAllDecorations()
35+
.filter(decorationFilter)
36+
.map((decoration) => decoration.range)
37+
if (editableRanges.length === 0) {
38+
return true
39+
}
40+
return editableRanges.some((editableRange) => editableRange.containsRange(range))
3541
}
3642
return false
3743
}
@@ -52,7 +58,13 @@ export function lockCodeWithoutDecoration (
5258
const originalTrigger = editor.trigger
5359
editor.trigger = function (source, handlerId, payload) {
5460
// Try to transform whole file pasting into a paste in the editable area only
55-
const lastEditableRange = decorations.length > 0 ? editor.getModel()?.getDecorationRange(decorations[decorations.length - 1]!) : null
61+
const editableRanges = editor
62+
.getModel()!
63+
.getAllDecorations()
64+
.filter(decorationFilter)
65+
.map((decoration) => decoration.range)
66+
const lastEditableRange =
67+
editableRanges.length > 0 ? editableRanges[editableRanges.length - 1] : undefined
5668
if (isPasteAction(handlerId, payload) && lastEditableRange != null) {
5769
const selections = editor.getSelections()
5870
const model = editor.getModel()!
@@ -63,10 +75,12 @@ export function lockCodeWithoutDecoration (
6375
if (wholeFileSelected) {
6476
const currentEditorValue = editor.getValue()
6577
const before = model.getOffsetAt(lastEditableRange.getStartPosition())
66-
const after = currentEditorValue.length - model.getOffsetAt(lastEditableRange.getEndPosition())
78+
const after =
79+
currentEditorValue.length - model.getOffsetAt(lastEditableRange.getEndPosition())
6780
if (
6881
currentEditorValue.slice(0, before) === payload.text.slice(0, before) &&
69-
currentEditorValue.slice(currentEditorValue.length - after) === payload.text.slice(payload.text.length - after)
82+
currentEditorValue.slice(currentEditorValue.length - after) ===
83+
payload.text.slice(payload.text.length - after)
7084
) {
7185
editor.setSelection(lastEditableRange)
7286
const newPayload: PastePayload = {
@@ -81,7 +95,7 @@ export function lockCodeWithoutDecoration (
8195

8296
if (['type', 'paste', 'cut'].includes(handlerId)) {
8397
const selections = editor.getSelections()
84-
if (selections != null && selections.some(range => !canEditRange(range))) {
98+
if (selections != null && selections.some((range) => !canEditRange(range))) {
8599
displayLockedCodeError(editor.getPosition()!)
86100
return
87101
}
@@ -107,16 +121,23 @@ export function lockCodeWithoutDecoration (
107121
if (model == null) {
108122
return
109123
}
110-
const originalApplyEdit: (operations: monaco.editor.IIdentifiedSingleEditOperation[], computeUndoEdits?: boolean) => void = model.applyEdits
111-
model.applyEdits = ((operations: monaco.editor.IIdentifiedSingleEditOperation[], computeUndoEdits?: boolean) => {
124+
const originalApplyEdit: (
125+
operations: monaco.editor.IIdentifiedSingleEditOperation[],
126+
computeUndoEdits?: boolean
127+
) => void = model.applyEdits
128+
model.applyEdits = ((
129+
operations: monaco.editor.IIdentifiedSingleEditOperation[],
130+
computeUndoEdits?: boolean
131+
) => {
112132
if (currentEditSource != null && allowChangeFromSources.includes(currentEditSource)) {
113133
return originalApplyEdit.call(model, operations, computeUndoEdits!)
114134
}
115-
const filteredOperations = operations
116-
.filter(operation => canEditRange(operation.range))
135+
const filteredOperations = operations.filter((operation) => canEditRange(operation.range))
117136
if (filteredOperations.length === 0 && operations.length > 0) {
118137
const firstRange = operations[0]!.range
119-
displayLockedCodeError(new monaco.Position(firstRange.startLineNumber, firstRange.startColumn))
138+
displayLockedCodeError(
139+
new monaco.Position(firstRange.startLineNumber, firstRange.startColumn)
140+
)
120141
}
121142
return originalApplyEdit.call(model, filteredOperations, computeUndoEdits!)
122143
}) as typeof model.applyEdits
@@ -160,13 +181,22 @@ export function lockCodeWithoutDecoration (
160181
return disposableStore
161182
}
162183

163-
export function hideCodeWithoutDecoration (editor: monaco.editor.IStandaloneCodeEditor, decorations: string[]): monaco.IDisposable {
184+
export function hideCodeWithoutDecoration (editor: monaco.editor.ICodeEditor, decorationFilter: (decoration: monaco.editor.IModelDecoration) => boolean): monaco.IDisposable {
164185
let otherHiddenAreas: monaco.IRange[] = editor._getViewModel()?.getHiddenAreas() ?? []
165186
function getHiddenAreas () {
166-
const model = editor.getModel()!
187+
const model = editor.getModel()
188+
if (model == null) {
189+
return []
190+
}
191+
192+
const decorations = model.getAllDecorations()
193+
.filter(decorationFilter)
194+
if (decorations.length === 0) {
195+
return otherHiddenAreas
196+
}
167197

168198
const ranges = decorations
169-
.map(decoration => model.getDecorationRange(decoration)!)
199+
.map(decoration => decoration.range)
170200
.sort((a, b) => a.startLineNumber - b.startLineNumber)
171201
// merge ranges
172202
.reduce<monaco.Range[]>((acc, range) => {
@@ -218,6 +248,14 @@ export function hideCodeWithoutDecoration (editor: monaco.editor.IStandaloneCode
218248
}
219249

220250
const disposableStore = new DisposableStore()
251+
252+
disposableStore.add(editor.onDidChangeModel(() => {
253+
otherHiddenAreas = editor._getViewModel()?.getHiddenAreas() ?? []
254+
updateHiddenAreas()
255+
}))
256+
disposableStore.add(editor.onDidChangeModelDecorations(() => {
257+
updateHiddenAreas()
258+
}))
221259
updateHiddenAreas()
222260

223261
disposableStore.add({

0 commit comments

Comments
 (0)