0
# Models and URIs
1
2
Model management, URI handling, and content operations in Monaco Editor.
3
4
## Core Concepts
5
6
### Models
7
Models represent the text content and metadata of files. Each model contains:
8
- Text content
9
- Language identifier
10
- URI for identification
11
- Edit history and version tracking
12
- Diagnostic markers and decorations
13
14
### URIs
15
URIs uniquely identify models and enable features like import resolution and schema validation. Monaco uses a virtual file system approach where each model has a unique URI.
16
17
## Core Classes
18
19
Monaco Editor provides fundamental classes for working with text positions, ranges, and selections.
20
21
### Position
22
23
```typescript { .api }
24
monaco.Position(lineNumber: number, column: number): Position
25
```
26
27
Creates a text position (line and column coordinates).
28
29
```typescript { .api }
30
interface Position {
31
readonly lineNumber: number;
32
readonly column: number;
33
}
34
```
35
36
**Static Methods:**
37
38
```typescript { .api }
39
monaco.Position.isIPosition(obj: any): boolean
40
```
41
42
Type guard to check if object is a position.
43
44
```typescript { .api }
45
monaco.Position.lift(position: IPosition): Position
46
```
47
48
Converts IPosition to Position instance.
49
50
```typescript { .api }
51
monaco.Position.compare(a: IPosition, b: IPosition): number
52
```
53
54
Compares two positions (-1, 0, or 1).
55
56
```typescript { .api }
57
monaco.Position.isBefore(a: IPosition, b: IPosition): boolean
58
```
59
60
Checks if position a is before position b.
61
62
```typescript { .api }
63
monaco.Position.isBeforeOrEqual(a: IPosition, b: IPosition): boolean
64
```
65
66
Checks if position a is before or equal to position b.
67
68
```typescript
69
// Create positions
70
const pos1 = new monaco.Position(1, 1); // Line 1, column 1
71
const pos2 = new monaco.Position(2, 5); // Line 2, column 5
72
73
// Compare positions
74
const comparison = monaco.Position.compare(pos1, pos2); // -1 (pos1 is before pos2)
75
const isBefore = monaco.Position.isBefore(pos1, pos2); // true
76
```
77
78
### Range
79
80
```typescript { .api }
81
monaco.Range(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number): Range
82
```
83
84
Creates a text range from start position to end position.
85
86
```typescript { .api }
87
interface Range {
88
readonly startLineNumber: number;
89
readonly startColumn: number;
90
readonly endLineNumber: number;
91
readonly endColumn: number;
92
}
93
```
94
95
**Static Methods:**
96
97
```typescript { .api }
98
monaco.Range.isEmpty(range: IRange): boolean
99
```
100
101
Checks if range is empty (start equals end).
102
103
```typescript { .api }
104
monaco.Range.isIRange(obj: any): boolean
105
```
106
107
Type guard to check if object is a range.
108
109
```typescript { .api }
110
monaco.Range.lift(range: IRange): Range
111
```
112
113
Converts IRange to Range instance.
114
115
```typescript { .api }
116
monaco.Range.containsPosition(range: IRange, position: IPosition): boolean
117
```
118
119
Checks if range contains the given position.
120
121
```typescript { .api }
122
monaco.Range.containsRange(range: IRange, otherRange: IRange): boolean
123
```
124
125
Checks if range fully contains another range.
126
127
```typescript { .api }
128
monaco.Range.intersectRanges(a: IRange, b: IRange): Range | null
129
```
130
131
Finds intersection of two ranges, returns null if no overlap.
132
133
```typescript
134
// Create ranges
135
const range1 = new monaco.Range(1, 1, 1, 10); // Line 1, columns 1-10
136
const range2 = new monaco.Range(1, 5, 2, 1); // Line 1 col 5 to line 2 col 1
137
138
// Range operations
139
const isEmpty = monaco.Range.isEmpty(range1); // false
140
const contains = monaco.Range.containsPosition(range1, new monaco.Position(1, 5)); // true
141
const intersection = monaco.Range.intersectRanges(range1, range2); // Overlapping portion
142
```
143
144
### Selection
145
146
```typescript { .api }
147
monaco.Selection(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number): Selection
148
```
149
150
Creates a text selection (extends Range with direction).
151
152
```typescript { .api }
153
interface Selection extends Range {
154
readonly selectionStartLineNumber: number;
155
readonly selectionStartColumn: number;
156
readonly positionLineNumber: number;
157
readonly positionColumn: number;
158
}
159
```
160
161
**Static Methods:**
162
163
```typescript { .api }
164
monaco.Selection.isISelection(obj: any): boolean
165
```
166
167
Type guard to check if object is a selection.
168
169
```typescript { .api }
170
monaco.Selection.createWithDirection(
171
startLineNumber: number,
172
startColumn: number,
173
endLineNumber: number,
174
endColumn: number,
175
direction: SelectionDirection
176
): Selection
177
```
178
179
Creates selection with explicit direction.
180
181
**Instance Methods:**
182
183
```typescript { .api }
184
selection.getDirection(): SelectionDirection
185
```
186
187
Gets the selection direction.
188
189
```typescript { .api }
190
selection.setEndPosition(endLineNumber: number, endColumn: number): Selection
191
```
192
193
Creates new selection with different end position.
194
195
```typescript { .api }
196
selection.getPosition(): Position
197
```
198
199
Gets cursor position (where selection ends).
200
201
```typescript
202
// Create selections
203
const selection = new monaco.Selection(1, 1, 1, 10); // Select line 1, columns 1-10
204
205
// Selection operations
206
const direction = selection.getDirection();
207
const cursorPos = selection.getPosition(); // Position(1, 10)
208
const newSelection = selection.setEndPosition(2, 5); // Extend to line 2
209
```
210
211
## Model Creation
212
213
### Creating Text Models
214
215
```typescript { .api }
216
monaco.editor.createModel(
217
value: string,
218
language?: string,
219
uri?: Uri
220
): ITextModel
221
```
222
223
Creates a new text model.
224
225
**Parameters:**
226
- `value`: Initial text content
227
- `language`: Language identifier (optional)
228
- `uri`: Unique identifier for the model (optional)
229
230
**Returns:** ITextModel instance
231
232
```typescript
233
// Basic model creation
234
const model = monaco.editor.createModel(
235
'console.log("Hello world!");',
236
'javascript'
237
);
238
239
// Model with specific URI
240
const model = monaco.editor.createModel(
241
'function add(a: number, b: number): number { return a + b; }',
242
'typescript',
243
monaco.Uri.parse('file:///math.ts')
244
);
245
```
246
247
### Getting Existing Models
248
249
```typescript { .api }
250
monaco.editor.getModel(uri: Uri): ITextModel | null
251
```
252
253
Gets an existing model by URI.
254
255
```typescript { .api }
256
monaco.editor.getModels(): ITextModel[]
257
```
258
259
Gets all existing models.
260
261
```typescript
262
const uri = monaco.Uri.parse('file:///example.ts');
263
const model = monaco.editor.getModel(uri);
264
265
if (model) {
266
console.log('Model found:', model.getValue());
267
}
268
```
269
270
## URI Management
271
272
### URI Creation
273
274
```typescript { .api }
275
monaco.Uri.parse(value: string): Uri
276
```
277
278
Parses a string into a URI.
279
280
```typescript { .api }
281
monaco.Uri.file(path: string): Uri
282
```
283
284
Creates a file URI from a path.
285
286
```typescript { .api }
287
monaco.Uri.from(components: UriComponents): Uri
288
```
289
290
Creates a URI from components.
291
292
```typescript { .api }
293
interface UriComponents {
294
scheme: string;
295
authority?: string;
296
path?: string;
297
query?: string;
298
fragment?: string;
299
}
300
```
301
302
```typescript
303
// Parse URI from string
304
const uri1 = monaco.Uri.parse('file:///path/to/file.ts');
305
306
// Create file URI
307
const uri2 = monaco.Uri.file('/path/to/file.ts');
308
309
// Create from components
310
const uri3 = monaco.Uri.from({
311
scheme: 'https',
312
authority: 'example.com',
313
path: '/api/data',
314
query: 'format=json'
315
});
316
```
317
318
### URI Properties and Methods
319
320
```typescript { .api }
321
interface Uri {
322
readonly scheme: string;
323
readonly authority: string;
324
readonly path: string;
325
readonly query: string;
326
readonly fragment: string;
327
readonly fsPath: string;
328
329
with(change: UriComponents): Uri;
330
toString(skipEncoding?: boolean): string;
331
toJSON(): UriComponents;
332
}
333
```
334
335
```typescript
336
const uri = monaco.Uri.parse('file:///src/main.ts');
337
338
console.log(uri.scheme); // 'file'
339
console.log(uri.path); // '/src/main.ts'
340
console.log(uri.fsPath); // '/src/main.ts' (filesystem path)
341
342
// Create modified URI
343
const newUri = uri.with({ path: '/src/utils.ts' });
344
```
345
346
## Model Operations
347
348
### Content Management
349
350
```typescript { .api }
351
model.getValue(eol?: EndOfLinePreference, preserveBOM?: boolean): string
352
```
353
354
Gets the model content.
355
356
```typescript { .api }
357
model.setValue(newValue: string): void
358
```
359
360
Sets the model content.
361
362
```typescript { .api }
363
model.getValueLength(): number
364
```
365
366
Gets the content length.
367
368
```typescript { .api }
369
model.getValueInRange(range: IRange, eol?: EndOfLinePreference): string
370
```
371
372
Gets content within a specific range.
373
374
```typescript
375
const model = monaco.editor.createModel('Hello\nWorld', 'text');
376
377
// Get full content
378
const content = model.getValue();
379
380
// Get content in range
381
const range = new monaco.Range(1, 1, 1, 5); // First line, chars 1-5
382
const partial = model.getValueInRange(range); // 'Hello'
383
384
// Set new content
385
model.setValue('New content');
386
```
387
388
### Language Management
389
390
```typescript { .api }
391
model.getLanguageId(): string
392
```
393
394
Gets the model's language identifier.
395
396
```typescript { .api }
397
monaco.editor.setModelLanguage(model: ITextModel, languageId: string): void
398
```
399
400
Sets the model's language.
401
402
```typescript
403
const model = monaco.editor.createModel('console.log("test")', 'javascript');
404
405
console.log(model.getLanguageId()); // 'javascript'
406
407
// Change language
408
monaco.editor.setModelLanguage(model, 'typescript');
409
console.log(model.getLanguageId()); // 'typescript'
410
```
411
412
### Position and Range Operations
413
414
```typescript { .api }
415
model.getPositionAt(offset: number): Position
416
```
417
418
Converts character offset to position.
419
420
```typescript { .api }
421
model.getOffsetAt(position: IPosition): number
422
```
423
424
Converts position to character offset.
425
426
```typescript { .api }
427
model.getLineContent(lineNumber: number): string
428
```
429
430
Gets the content of a specific line.
431
432
```typescript { .api }
433
model.getLineCount(): number
434
```
435
436
Gets the number of lines.
437
438
```typescript { .api }
439
model.getLineMaxColumn(lineNumber: number): number
440
```
441
442
Gets the maximum column for a line.
443
444
```typescript
445
const model = monaco.editor.createModel('Hello\nWorld\nTest', 'text');
446
447
// Position and offset conversions
448
const position = model.getPositionAt(7); // Position after 'Hello\nW'
449
console.log(position); // { lineNumber: 2, column: 2 }
450
451
const offset = model.getOffsetAt(new monaco.Position(2, 2));
452
console.log(offset); // 7
453
454
// Line operations
455
console.log(model.getLineCount()); // 3
456
console.log(model.getLineContent(2)); // 'World'
457
console.log(model.getLineMaxColumn(1)); // 6 (length of 'Hello' + 1)
458
```
459
460
## Text Editing
461
462
### Edit Operations
463
464
```typescript { .api }
465
model.pushEditOperations(
466
beforeCursorState: Selection[] | null,
467
editOperations: IIdentifiedSingleEditOperation[],
468
cursorStateComputer?: ICursorStateComputer | null
469
): Selection[] | null
470
```
471
472
Applies edit operations to the model.
473
474
```typescript { .api }
475
interface IIdentifiedSingleEditOperation {
476
range: IRange;
477
text: string | null;
478
forceMoveMarkers?: boolean;
479
}
480
```
481
482
```typescript
483
const model = monaco.editor.createModel('Hello World', 'text');
484
485
// Replace 'World' with 'Monaco'
486
const editOperation = {
487
range: new monaco.Range(1, 7, 1, 12), // 'World' range
488
text: 'Monaco'
489
};
490
491
model.pushEditOperations([], [editOperation], null);
492
console.log(model.getValue()); // 'Hello Monaco'
493
```
494
495
### Batch Operations
496
497
```typescript { .api }
498
model.applyEdits(operations: IIdentifiedSingleEditOperation[]): void
499
```
500
501
Applies multiple edit operations.
502
503
```typescript
504
const operations = [
505
{
506
range: new monaco.Range(1, 1, 1, 1),
507
text: '// Comment\n'
508
},
509
{
510
range: new monaco.Range(1, 7, 1, 12),
511
text: 'Monaco'
512
}
513
];
514
515
model.applyEdits(operations);
516
```
517
518
## Version Tracking
519
520
### Version Information
521
522
```typescript { .api }
523
model.getVersionId(): number
524
```
525
526
Gets the current version ID.
527
528
```typescript { .api }
529
model.getAlternativeVersionId(): number
530
```
531
532
Gets the alternative version ID.
533
534
```typescript
535
const model = monaco.editor.createModel('Initial content', 'text');
536
console.log(model.getVersionId()); // 1
537
538
model.setValue('Modified content');
539
console.log(model.getVersionId()); // 2
540
```
541
542
## Event Handling
543
544
### Content Change Events
545
546
```typescript { .api }
547
model.onDidChangeContent(listener: (e: IModelContentChangedEvent) => void): IDisposable
548
```
549
550
Fired when model content changes.
551
552
```typescript { .api }
553
interface IModelContentChangedEvent {
554
readonly changes: IModelContentChange[];
555
readonly eol: string;
556
readonly versionId: number;
557
readonly isUndoing: boolean;
558
readonly isRedoing: boolean;
559
readonly isFlush: boolean;
560
}
561
```
562
563
```typescript
564
const disposable = model.onDidChangeContent((e) => {
565
console.log('Content changed, version:', e.versionId);
566
console.log('Changes:', e.changes);
567
});
568
```
569
570
### Language Change Events
571
572
```typescript { .api }
573
model.onDidChangeLanguage(listener: (e: IModelLanguageChangedEvent) => void): IDisposable
574
```
575
576
Fired when model language changes.
577
578
### Disposal Events
579
580
```typescript { .api }
581
model.onWillDispose(listener: () => void): IDisposable
582
```
583
584
Fired before model disposal.
585
586
## Markers and Diagnostics
587
588
### Setting Markers
589
590
```typescript { .api }
591
monaco.editor.setModelMarkers(
592
model: ITextModel,
593
owner: string,
594
markers: IMarkerData[]
595
): void
596
```
597
598
Sets diagnostic markers for a model.
599
600
```typescript { .api }
601
interface IMarkerData {
602
severity: MarkerSeverity;
603
message: string;
604
startLineNumber: number;
605
startColumn: number;
606
endLineNumber: number;
607
endColumn: number;
608
code?: string | { value: string; target: Uri };
609
source?: string;
610
tags?: MarkerTag[];
611
relatedInformation?: IRelatedInformation[];
612
}
613
```
614
615
```typescript { .api }
616
enum MarkerSeverity {
617
Hint = 1,
618
Info = 2,
619
Warning = 4,
620
Error = 8
621
}
622
```
623
624
```typescript
625
// Set error markers
626
monaco.editor.setModelMarkers(model, 'typescript', [
627
{
628
severity: monaco.MarkerSeverity.Error,
629
message: 'Variable is not defined',
630
startLineNumber: 1,
631
startColumn: 1,
632
endLineNumber: 1,
633
endColumn: 5,
634
code: 'TS2304'
635
}
636
]);
637
```
638
639
### Getting Markers
640
641
```typescript { .api }
642
monaco.editor.getModelMarkers(filter: { owner?: string; resource?: Uri; take?: number }): IMarker[]
643
```
644
645
Gets markers for models.
646
647
```typescript
648
// Get all markers for a model
649
const markers = monaco.editor.getModelMarkers({
650
resource: model.getUri()
651
});
652
653
// Get TypeScript-specific markers
654
const tsMarkers = monaco.editor.getModelMarkers({
655
owner: 'typescript'
656
});
657
```
658
659
## Model Disposal
660
661
### Disposing Models
662
663
```typescript { .api }
664
model.dispose(): void
665
```
666
667
Disposes a model and frees resources.
668
669
```typescript
670
// Always dispose models when done
671
model.dispose();
672
```
673
674
### Automatic Cleanup
675
676
```typescript { .api }
677
monaco.editor.onDidCreateModel(listener: (model: ITextModel) => void): IDisposable
678
```
679
680
Fired when a model is created.
681
682
```typescript { .api }
683
monaco.editor.onWillDisposeModel(listener: (model: ITextModel) => void): IDisposable
684
```
685
686
Fired before a model is disposed.
687
688
```typescript
689
// Track model lifecycle
690
monaco.editor.onDidCreateModel((model) => {
691
console.log('Model created:', model.getUri().toString());
692
});
693
694
monaco.editor.onWillDisposeModel((model) => {
695
console.log('Model disposing:', model.getUri().toString());
696
});
697
```
698
699
## Core Interface Definitions
700
701
### IPosition and IRange
702
703
```typescript { .api }
704
interface IPosition {
705
readonly lineNumber: number;
706
readonly column: number;
707
}
708
709
interface IRange {
710
readonly startLineNumber: number;
711
readonly startColumn: number;
712
readonly endLineNumber: number;
713
readonly endColumn: number;
714
}
715
716
interface ISelection extends IRange {
717
readonly selectionStartLineNumber: number;
718
readonly selectionStartColumn: number;
719
readonly positionLineNumber: number;
720
readonly positionColumn: number;
721
}
722
```
723
724
### Editor State Options
725
726
```typescript { .api }
727
interface IEditorStateOptions {
728
canUndoRedoOnly?: boolean;
729
contributionsState?: boolean;
730
cursorState?: boolean;
731
viewState?: boolean;
732
}
733
```
734
735
Options for controlling what editor state to preserve.