Skip to content

Commit

Permalink
fix: render examples as yaml on hover (#947)
Browse files Browse the repository at this point in the history
Co-authored-by: Muthurajan Sivasubramanian <93245779+msivasubramaniaan@users.noreply.github.com>
  • Loading branch information
twelvelabs and msivasubramaniaan committed Jan 5, 2024
1 parent 5458ed3 commit dfccc6f
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 28 deletions.
48 changes: 24 additions & 24 deletions src/languageservice/services/yamlHover.ts
Expand Up @@ -19,6 +19,7 @@ import * as path from 'path';
import { Telemetry } from '../telemetry';
import { convertErrorToTelemetryMsg } from '../utils/objects';
import { ASTNode } from 'vscode-json-languageservice';
import { stringify as stringifyYAML } from 'yaml';

export class YAMLHover {
private shouldHover: boolean;
Expand Down Expand Up @@ -87,11 +88,6 @@ export class YAMLHover {
);

const createHover = (contents: string): Hover => {
if (this.indentation !== undefined) {
const indentationMatchRegex = new RegExp(` {${this.indentation.length}}`, 'g');
contents = contents.replace(indentationMatchRegex, '&emsp;');
}

const markupContent: MarkupContent = {
kind: MarkupKind.Markdown,
value: contents,
Expand Down Expand Up @@ -120,12 +116,12 @@ export class YAMLHover {
matchingSchemas.every((s) => {
if ((s.node === node || (node.type === 'property' && node.valueNode === s.node)) && !s.inverted && s.schema) {
title = title || s.schema.title || s.schema.closestTitle;
markdownDescription = markdownDescription || s.schema.markdownDescription || toMarkdown(s.schema.description);
markdownDescription = markdownDescription || s.schema.markdownDescription || this.toMarkdown(s.schema.description);
if (s.schema.enum) {
if (s.schema.markdownEnumDescriptions) {
markdownEnumDescriptions = s.schema.markdownEnumDescriptions;
} else if (s.schema.enumDescriptions) {
markdownEnumDescriptions = s.schema.enumDescriptions.map(toMarkdown);
markdownEnumDescriptions = s.schema.enumDescriptions.map(this.toMarkdown, this);
} else {
markdownEnumDescriptions = [];
}
Expand All @@ -145,7 +141,7 @@ export class YAMLHover {
markdownDescription = '';
s.schema.anyOf.forEach((childSchema: JSONSchema, index: number) => {
title += childSchema.title || s.schema.closestTitle || '';
markdownDescription += childSchema.markdownDescription || toMarkdown(childSchema.description) || '';
markdownDescription += childSchema.markdownDescription || this.toMarkdown(childSchema.description) || '';
if (index !== s.schema.anyOf.length - 1) {
title += ' || ';
markdownDescription += ' || ';
Expand All @@ -156,15 +152,15 @@ export class YAMLHover {
}
if (s.schema.examples) {
s.schema.examples.forEach((example) => {
markdownExamples.push(JSON.stringify(example, null, 2));
markdownExamples.push(stringifyYAML(example, null, 2));
});
}
}
return true;
});
let result = '';
if (title) {
result = '#### ' + toMarkdown(title);
result = '#### ' + this.toMarkdown(title);
}
if (markdownDescription) {
result = ensureLineBreak(result);
Expand All @@ -182,10 +178,10 @@ export class YAMLHover {
});
}
if (markdownExamples.length !== 0) {
result = ensureLineBreak(result);
result += 'Examples:\n\n';
markdownExamples.forEach((example) => {
result += `* \`\`\`${example}\`\`\`\n`;
result = ensureLineBreak(result);
result += 'Example:\n\n';
result += `\`\`\`yaml\n${example}\`\`\`\n`;
});
}
if (result.length > 0 && schema.schema.url) {
Expand All @@ -197,6 +193,21 @@ export class YAMLHover {
return null;
});
}

// copied from https://github.com/microsoft/vscode-json-languageservice/blob/2ea5ad3d2ffbbe40dea11cfe764a502becf113ce/src/services/jsonHover.ts#L112
private toMarkdown(plain: string | undefined): string | undefined {
if (plain) {
let escaped = plain.replace(/([^\n\r])(\r?\n)([^\n\r])/gm, '$1\n\n$3'); // single new lines to \n\n (Markdown paragraph)
escaped = escaped.replace(/[\\`*_{}[\]()#+\-.!]/g, '\\$&'); // escape markdown syntax tokens: http://daringfireball.net/projects/markdown/syntax#backslash
if (this.indentation !== undefined) {
// escape indentation whitespace to prevent it from being converted to markdown code blocks.
const indentationMatchRegex = new RegExp(` {${this.indentation.length}}`, 'g');
escaped = escaped.replace(indentationMatchRegex, '&emsp;');
}
return escaped;
}
return undefined;
}
}

interface markdownEnum {
Expand Down Expand Up @@ -226,17 +237,6 @@ function getSchemaName(schema: JSONSchema): string {
return result;
}

// copied from https://github.com/microsoft/vscode-json-languageservice/blob/2ea5ad3d2ffbbe40dea11cfe764a502becf113ce/src/services/jsonHover.ts#L112
function toMarkdown(plain: string): string;
function toMarkdown(plain: string | undefined): string | undefined;
function toMarkdown(plain: string | undefined): string | undefined {
if (plain) {
const res = plain.replace(/([^\n\r])(\r?\n)([^\n\r])/gm, '$1\n\n$3'); // single new lines to \n\n (Markdown paragraph)
return res.replace(/[\\`*_{}[\]()#+\-.!]/g, '\\$&'); // escape markdown syntax tokens: http://daringfireball.net/projects/markdown/syntax#backslash
}
return undefined;
}

// copied from https://github.com/microsoft/vscode-json-languageservice/blob/2ea5ad3d2ffbbe40dea11cfe764a502becf113ce/src/services/jsonHover.ts#L122
function toMarkdownCodeBlock(content: string): string {
// see https://daringfireball.net/projects/markdown/syntax#precode
Expand Down
23 changes: 19 additions & 4 deletions test/hover.test.ts
Expand Up @@ -595,7 +595,14 @@ Source: [${SCHEMA_ID}](file:///${SCHEMA_ID})`
type: 'string',
description: 'should return this description',
enum: ['cat', 'dog'],
examples: ['cat', 'dog'],
examples: [
'cat',
{
animal: {
type: 'dog',
},
},
],
},
},
});
Expand All @@ -613,10 +620,18 @@ Allowed Values:
* \`cat\`
* \`dog\`
Examples:
Example:
\`\`\`yaml
cat
\`\`\`
Example:
* \`\`\`"cat"\`\`\`
* \`\`\`"dog"\`\`\`
\`\`\`yaml
animal:
type: dog
\`\`\`
Source: [${SCHEMA_ID}](file:///${SCHEMA_ID})`
);
Expand Down

0 comments on commit dfccc6f

Please sign in to comment.