Skip to content

Commit dfccc6f

Browse files
fix: render examples as yaml on hover (#947)
Co-authored-by: Muthurajan Sivasubramanian <[email protected]>
1 parent 5458ed3 commit dfccc6f

File tree

2 files changed

+43
-28
lines changed

2 files changed

+43
-28
lines changed

src/languageservice/services/yamlHover.ts

+24-24
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import * as path from 'path';
1919
import { Telemetry } from '../telemetry';
2020
import { convertErrorToTelemetryMsg } from '../utils/objects';
2121
import { ASTNode } from 'vscode-json-languageservice';
22+
import { stringify as stringifyYAML } from 'yaml';
2223

2324
export class YAMLHover {
2425
private shouldHover: boolean;
@@ -87,11 +88,6 @@ export class YAMLHover {
8788
);
8889

8990
const createHover = (contents: string): Hover => {
90-
if (this.indentation !== undefined) {
91-
const indentationMatchRegex = new RegExp(` {${this.indentation.length}}`, 'g');
92-
contents = contents.replace(indentationMatchRegex, '&emsp;');
93-
}
94-
9591
const markupContent: MarkupContent = {
9692
kind: MarkupKind.Markdown,
9793
value: contents,
@@ -120,12 +116,12 @@ export class YAMLHover {
120116
matchingSchemas.every((s) => {
121117
if ((s.node === node || (node.type === 'property' && node.valueNode === s.node)) && !s.inverted && s.schema) {
122118
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);
124120
if (s.schema.enum) {
125121
if (s.schema.markdownEnumDescriptions) {
126122
markdownEnumDescriptions = s.schema.markdownEnumDescriptions;
127123
} else if (s.schema.enumDescriptions) {
128-
markdownEnumDescriptions = s.schema.enumDescriptions.map(toMarkdown);
124+
markdownEnumDescriptions = s.schema.enumDescriptions.map(this.toMarkdown, this);
129125
} else {
130126
markdownEnumDescriptions = [];
131127
}
@@ -145,7 +141,7 @@ export class YAMLHover {
145141
markdownDescription = '';
146142
s.schema.anyOf.forEach((childSchema: JSONSchema, index: number) => {
147143
title += childSchema.title || s.schema.closestTitle || '';
148-
markdownDescription += childSchema.markdownDescription || toMarkdown(childSchema.description) || '';
144+
markdownDescription += childSchema.markdownDescription || this.toMarkdown(childSchema.description) || '';
149145
if (index !== s.schema.anyOf.length - 1) {
150146
title += ' || ';
151147
markdownDescription += ' || ';
@@ -156,15 +152,15 @@ export class YAMLHover {
156152
}
157153
if (s.schema.examples) {
158154
s.schema.examples.forEach((example) => {
159-
markdownExamples.push(JSON.stringify(example, null, 2));
155+
markdownExamples.push(stringifyYAML(example, null, 2));
160156
});
161157
}
162158
}
163159
return true;
164160
});
165161
let result = '';
166162
if (title) {
167-
result = '#### ' + toMarkdown(title);
163+
result = '#### ' + this.toMarkdown(title);
168164
}
169165
if (markdownDescription) {
170166
result = ensureLineBreak(result);
@@ -182,10 +178,10 @@ export class YAMLHover {
182178
});
183179
}
184180
if (markdownExamples.length !== 0) {
185-
result = ensureLineBreak(result);
186-
result += 'Examples:\n\n';
187181
markdownExamples.forEach((example) => {
188-
result += `* \`\`\`${example}\`\`\`\n`;
182+
result = ensureLineBreak(result);
183+
result += 'Example:\n\n';
184+
result += `\`\`\`yaml\n${example}\`\`\`\n`;
189185
});
190186
}
191187
if (result.length > 0 && schema.schema.url) {
@@ -197,6 +193,21 @@ export class YAMLHover {
197193
return null;
198194
});
199195
}
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, '&emsp;');
206+
}
207+
return escaped;
208+
}
209+
return undefined;
210+
}
200211
}
201212

202213
interface markdownEnum {
@@ -226,17 +237,6 @@ function getSchemaName(schema: JSONSchema): string {
226237
return result;
227238
}
228239

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-
240240
// copied from https://github.com/microsoft/vscode-json-languageservice/blob/2ea5ad3d2ffbbe40dea11cfe764a502becf113ce/src/services/jsonHover.ts#L122
241241
function toMarkdownCodeBlock(content: string): string {
242242
// see https://daringfireball.net/projects/markdown/syntax#precode

test/hover.test.ts

+19-4
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,14 @@ Source: [${SCHEMA_ID}](file:///${SCHEMA_ID})`
595595
type: 'string',
596596
description: 'should return this description',
597597
enum: ['cat', 'dog'],
598-
examples: ['cat', 'dog'],
598+
examples: [
599+
'cat',
600+
{
601+
animal: {
602+
type: 'dog',
603+
},
604+
},
605+
],
599606
},
600607
},
601608
});
@@ -613,10 +620,18 @@ Allowed Values:
613620
* \`cat\`
614621
* \`dog\`
615622
616-
Examples:
623+
Example:
624+
625+
\`\`\`yaml
626+
cat
627+
\`\`\`
628+
629+
Example:
617630
618-
* \`\`\`"cat"\`\`\`
619-
* \`\`\`"dog"\`\`\`
631+
\`\`\`yaml
632+
animal:
633+
type: dog
634+
\`\`\`
620635
621636
Source: [${SCHEMA_ID}](file:///${SCHEMA_ID})`
622637
);

0 commit comments

Comments
 (0)