| 1 | /* CECB DecorationLayerManager (ADR 0163 §2.6, monaco-presentation-projection-v1). */ |
| 2 | (function (global) { |
| 3 | 'use strict'; |
| 4 | |
| 5 | function createDecorationLayerManager() { |
| 6 | const decorationSets = new Map(); |
| 7 | |
| 8 | function applyWholeLineClass(className, options) { |
| 9 | options.isWholeLine = true; |
| 10 | if (!className) return; |
| 11 | if (className.startsWith('squiggly-')) { |
| 12 | options.inlineClassName = className; |
| 13 | } else { |
| 14 | options.className = className; |
| 15 | } |
| 16 | } |
| 17 | |
| 18 | function resolveRange(d, model, monaco) { |
| 19 | if (d.startLine != null && d.startLine > 0) { |
| 20 | const startLine = d.startLine; |
| 21 | const endLine = d.endLine && d.endLine > 0 ? d.endLine : startLine; |
| 22 | const startCol = d.startColumn && d.startColumn > 0 ? d.startColumn : 1; |
| 23 | const endCol = d.endColumn && d.endColumn > 0 |
| 24 | ? d.endColumn |
| 25 | : model.getLineMaxColumn(Math.min(endLine, model.getLineCount())); |
| 26 | return new monaco.Range( |
| 27 | startLine, |
| 28 | startCol, |
| 29 | Math.min(endLine, model.getLineCount()), |
| 30 | endCol |
| 31 | ); |
| 32 | } |
| 33 | |
| 34 | const maxOffset = model.getValueLength(); |
| 35 | const start = Math.max(0, Math.min(d.startOffset ?? 0, maxOffset)); |
| 36 | const end = Math.max(start, Math.min(start + Math.max(0, d.length ?? 0), maxOffset)); |
| 37 | return monaco.Range.fromPositions(model.getPositionAt(start), model.getPositionAt(end)); |
| 38 | } |
| 39 | |
| 40 | function toMonacoDecoration(d, model, monaco) { |
| 41 | const className = d.className || ''; |
| 42 | const options = { |
| 43 | hoverMessage: d.hoverMessage ? { value: d.hoverMessage } : undefined, |
| 44 | glyphMarginClassName: d.glyphMarginClassName || undefined, |
| 45 | }; |
| 46 | if (d.isWholeLine) { |
| 47 | applyWholeLineClass(className, options); |
| 48 | } else if (className) { |
| 49 | options.inlineClassName = className; |
| 50 | } |
| 51 | return { range: resolveRange(d, model, monaco), options }; |
| 52 | } |
| 53 | |
| 54 | return { |
| 55 | apply(setId, decorations, editor, monaco, normalizeSetId) { |
| 56 | if (!editor) return; |
| 57 | const model = editor.getModel(); |
| 58 | if (!model) return; |
| 59 | const normalizedId = normalizeSetId(setId); |
| 60 | const monacoDecos = (decorations || []).map((d) => toMonacoDecoration(d, model, monaco)); |
| 61 | const handles = editor.deltaDecorations(decorationSets.get(normalizedId) || [], monacoDecos); |
| 62 | decorationSets.set(normalizedId, handles); |
| 63 | }, |
| 64 | }; |
| 65 | } |
| 66 | |
| 67 | global.CideDecorationLayerManager = { create: createDecorationLayerManager }; |
| 68 | })(typeof window !== 'undefined' ? window : globalThis); |
| 69 | |