@@ -2,39 +2,51 @@ import type * as MonacoTypes from 'monaco-editor'
22import { XMLValidator } from 'fast-xml-parser'
33
44export function setupXMLValidation ( monaco : typeof MonacoTypes ) {
5- const xmlModels = new Set < MonacoTypes . editor . ITextModel > ( )
5+ const markerId = 'xml-validation'
6+ const contentChangeListeners = new Map < MonacoTypes . editor . ITextModel , MonacoTypes . IDisposable > ( )
67
78 monaco . editor . onWillDisposeModel ( model => {
8- xmlModels . delete ( model )
9+ contentChangeListeners . delete ( model )
910 } )
1011
11- monaco . editor . onDidChangeModelLanguage ( event => {
12- const model = event . model
13- if ( model . getModeId ( ) === 'xml' && ! xmlModels . has ( model ) ) {
14- xmlModels . add ( model )
15- model . onDidChangeContent ( ( ) => {
16- const markers : MonacoTypes . editor . IMarkerData [ ] = [ ]
17- const text = model . getValue ( )
18-
19- if ( text . trim ( ) ) {
20- const validationResult = XMLValidator . validate ( text , {
21- allowBooleanAttributes : true ,
22- } )
23-
24- if ( validationResult !== true ) {
25- markers . push ( {
26- severity : monaco . MarkerSeverity . Error ,
27- startLineNumber : validationResult . err . line ,
28- startColumn : validationResult . err . col ,
29- endLineNumber : validationResult . err . line ,
30- endColumn : validationResult . err . col + 10 , // the 10 is totally arbitrary here
31- message : validationResult . err . msg ,
32- } )
33- }
34- }
35-
36- monaco . editor . setModelMarkers ( model , 'xml-validation' , markers )
12+ function validate ( model : MonacoTypes . editor . ITextModel ) {
13+ const markers : MonacoTypes . editor . IMarkerData [ ] = [ ]
14+ const text = model . getValue ( )
15+
16+ if ( text . trim ( ) ) {
17+ const validationResult = XMLValidator . validate ( text , {
18+ allowBooleanAttributes : true ,
3719 } )
20+
21+ if ( validationResult !== true ) {
22+ markers . push ( {
23+ severity : monaco . MarkerSeverity . Error ,
24+ startLineNumber : validationResult . err . line ,
25+ startColumn : validationResult . err . col ,
26+ endLineNumber : validationResult . err . line ,
27+ endColumn : model . getLineContent ( validationResult . err . line ) . length + 1 ,
28+ message : validationResult . err . msg ,
29+ } )
30+ }
31+ }
32+
33+ monaco . editor . setModelMarkers ( model , markerId , markers )
34+ }
35+
36+ monaco . editor . onDidChangeModelLanguage ( ( { model } ) => {
37+ const isXml = model . getModeId ( ) === 'xml'
38+ const listener = contentChangeListeners . get ( model )
39+
40+ if ( isXml && ! listener ) {
41+ contentChangeListeners . set (
42+ model ,
43+ model . onDidChangeContent ( ( ) => validate ( model ) )
44+ )
45+ validate ( model )
46+ } else if ( ! isXml && listener ) {
47+ listener . dispose ( )
48+ contentChangeListeners . delete ( model )
49+ monaco . editor . setModelMarkers ( model , markerId , [ ] )
3850 }
3951 } )
4052}
0 commit comments