@@ -19,6 +19,7 @@ import * as path from 'path';
19
19
import { Telemetry } from '../telemetry' ;
20
20
import { convertErrorToTelemetryMsg } from '../utils/objects' ;
21
21
import { ASTNode } from 'vscode-json-languageservice' ;
22
+ import { stringify as stringifyYAML } from 'yaml' ;
22
23
23
24
export class YAMLHover {
24
25
private shouldHover : boolean ;
@@ -87,11 +88,6 @@ export class YAMLHover {
87
88
) ;
88
89
89
90
const createHover = ( contents : string ) : Hover => {
90
- if ( this . indentation !== undefined ) {
91
- const indentationMatchRegex = new RegExp ( ` {${ this . indentation . length } }` , 'g' ) ;
92
- contents = contents . replace ( indentationMatchRegex , ' ' ) ;
93
- }
94
-
95
91
const markupContent : MarkupContent = {
96
92
kind : MarkupKind . Markdown ,
97
93
value : contents ,
@@ -120,12 +116,12 @@ export class YAMLHover {
120
116
matchingSchemas . every ( ( s ) => {
121
117
if ( ( s . node === node || ( node . type === 'property' && node . valueNode === s . node ) ) && ! s . inverted && s . schema ) {
122
118
title = title || s . schema . title || s . schema . closestTitle ;
123
- markdownDescription = markdownDescription || s . schema . markdownDescription || toMarkdown ( s . schema . description ) ;
119
+ markdownDescription = markdownDescription || s . schema . markdownDescription || this . toMarkdown ( s . schema . description ) ;
124
120
if ( s . schema . enum ) {
125
121
if ( s . schema . markdownEnumDescriptions ) {
126
122
markdownEnumDescriptions = s . schema . markdownEnumDescriptions ;
127
123
} else if ( s . schema . enumDescriptions ) {
128
- markdownEnumDescriptions = s . schema . enumDescriptions . map ( toMarkdown ) ;
124
+ markdownEnumDescriptions = s . schema . enumDescriptions . map ( this . toMarkdown , this ) ;
129
125
} else {
130
126
markdownEnumDescriptions = [ ] ;
131
127
}
@@ -145,7 +141,7 @@ export class YAMLHover {
145
141
markdownDescription = '' ;
146
142
s . schema . anyOf . forEach ( ( childSchema : JSONSchema , index : number ) => {
147
143
title += childSchema . title || s . schema . closestTitle || '' ;
148
- markdownDescription += childSchema . markdownDescription || toMarkdown ( childSchema . description ) || '' ;
144
+ markdownDescription += childSchema . markdownDescription || this . toMarkdown ( childSchema . description ) || '' ;
149
145
if ( index !== s . schema . anyOf . length - 1 ) {
150
146
title += ' || ' ;
151
147
markdownDescription += ' || ' ;
@@ -156,15 +152,15 @@ export class YAMLHover {
156
152
}
157
153
if ( s . schema . examples ) {
158
154
s . schema . examples . forEach ( ( example ) => {
159
- markdownExamples . push ( JSON . stringify ( example , null , 2 ) ) ;
155
+ markdownExamples . push ( stringifyYAML ( example , null , 2 ) ) ;
160
156
} ) ;
161
157
}
162
158
}
163
159
return true ;
164
160
} ) ;
165
161
let result = '' ;
166
162
if ( title ) {
167
- result = '#### ' + toMarkdown ( title ) ;
163
+ result = '#### ' + this . toMarkdown ( title ) ;
168
164
}
169
165
if ( markdownDescription ) {
170
166
result = ensureLineBreak ( result ) ;
@@ -182,10 +178,10 @@ export class YAMLHover {
182
178
} ) ;
183
179
}
184
180
if ( markdownExamples . length !== 0 ) {
185
- result = ensureLineBreak ( result ) ;
186
- result += 'Examples:\n\n' ;
187
181
markdownExamples . forEach ( ( example ) => {
188
- result += `* \`\`\`${ example } \`\`\`\n` ;
182
+ result = ensureLineBreak ( result ) ;
183
+ result += 'Example:\n\n' ;
184
+ result += `\`\`\`yaml\n${ example } \`\`\`\n` ;
189
185
} ) ;
190
186
}
191
187
if ( result . length > 0 && schema . schema . url ) {
@@ -197,6 +193,21 @@ export class YAMLHover {
197
193
return null ;
198
194
} ) ;
199
195
}
196
+
197
+ // copied from https://github.com/microsoft/vscode-json-languageservice/blob/2ea5ad3d2ffbbe40dea11cfe764a502becf113ce/src/services/jsonHover.ts#L112
198
+ private toMarkdown ( plain : string | undefined ) : string | undefined {
199
+ if ( plain ) {
200
+ let escaped = plain . replace ( / ( [ ^ \n \r ] ) ( \r ? \n ) ( [ ^ \n \r ] ) / gm, '$1\n\n$3' ) ; // single new lines to \n\n (Markdown paragraph)
201
+ escaped = escaped . replace ( / [ \\ ` * _ { } [ \] ( ) # + \- . ! ] / g, '\\$&' ) ; // escape markdown syntax tokens: http://daringfireball.net/projects/markdown/syntax#backslash
202
+ if ( this . indentation !== undefined ) {
203
+ // escape indentation whitespace to prevent it from being converted to markdown code blocks.
204
+ const indentationMatchRegex = new RegExp ( ` {${ this . indentation . length } }` , 'g' ) ;
205
+ escaped = escaped . replace ( indentationMatchRegex , ' ' ) ;
206
+ }
207
+ return escaped ;
208
+ }
209
+ return undefined ;
210
+ }
200
211
}
201
212
202
213
interface markdownEnum {
@@ -226,17 +237,6 @@ function getSchemaName(schema: JSONSchema): string {
226
237
return result ;
227
238
}
228
239
229
- // copied from https://github.com/microsoft/vscode-json-languageservice/blob/2ea5ad3d2ffbbe40dea11cfe764a502becf113ce/src/services/jsonHover.ts#L112
230
- function toMarkdown ( plain : string ) : string ;
231
- function toMarkdown ( plain : string | undefined ) : string | undefined ;
232
- function toMarkdown ( plain : string | undefined ) : string | undefined {
233
- if ( plain ) {
234
- const res = plain . replace ( / ( [ ^ \n \r ] ) ( \r ? \n ) ( [ ^ \n \r ] ) / gm, '$1\n\n$3' ) ; // single new lines to \n\n (Markdown paragraph)
235
- return res . replace ( / [ \\ ` * _ { } [ \] ( ) # + \- . ! ] / g, '\\$&' ) ; // escape markdown syntax tokens: http://daringfireball.net/projects/markdown/syntax#backslash
236
- }
237
- return undefined ;
238
- }
239
-
240
240
// copied from https://github.com/microsoft/vscode-json-languageservice/blob/2ea5ad3d2ffbbe40dea11cfe764a502becf113ce/src/services/jsonHover.ts#L122
241
241
function toMarkdownCodeBlock ( content : string ) : string {
242
242
// see https://daringfireball.net/projects/markdown/syntax#precode
0 commit comments