From d62c51033dcdc0366c360c0751a73e933694c71f Mon Sep 17 00:00:00 2001 From: Pinghao Wu Date: Sat, 30 May 2026 22:14:46 +0800 Subject: [PATCH 1/4] feat(completion): introduce formatInfo to control description rendering like formatHover in hover --- src/features/completion.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/features/completion.ts b/src/features/completion.ts index 2d12c6d..b24226f 100644 --- a/src/features/completion.ts +++ b/src/features/completion.ts @@ -55,6 +55,7 @@ class CompletionCollector { export interface JSONCompletionOptions { mode?: JSONMode; jsonParser?: DocumentParser; + formatInfo?: (description: string) => HTMLElement; } function isRealSchema( @@ -68,6 +69,11 @@ function isRealSchema( ); } +const defaultFormatInfo = (description: string) => + el("div", { + inner: renderMarkdown(description), + }); + export class JSONCompletion { private originalSchema: JSONSchema7 | null = null; /** @@ -81,12 +87,14 @@ export class JSONCompletion { private laxSchema: JSONSchema7 | null = null; private mode: JSONMode = MODES.JSON; private parser: DocumentParser; + private formatInfo = defaultFormatInfo; // private lastKnownValidData: object | null = null; constructor(private opts: JSONCompletionOptions) { this.mode = opts.mode ?? MODES.JSON; this.parser = this.opts?.jsonParser ?? getDefaultParser(this.mode); + this.formatInfo = opts.formatInfo ?? defaultFormatInfo; } public doComplete(ctx: CompletionContext) { @@ -360,10 +368,7 @@ export class JSONCompletion { ), type: "property", detail: typeStr, - info: () => - el("div", { - inner: renderMarkdown(description), - }), + info: () => this.formatInfo(description), }; collector.add(this.applySnippetCompletion(completion)); } From dc7b2842f03ee3400febf5eb64ca0fbf4de7c351 Mon Sep 17 00:00:00 2001 From: Pinghao Wu Date: Sat, 30 May 2026 22:21:46 +0800 Subject: [PATCH 2/4] fix(completion): apply description renderer also to enums --- src/features/__tests__/json-completion.spec.ts | 10 ++++++---- src/features/completion.ts | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/features/__tests__/json-completion.spec.ts b/src/features/__tests__/json-completion.spec.ts index 03ea3d8..a583f23 100644 --- a/src/features/__tests__/json-completion.spec.ts +++ b/src/features/__tests__/json-completion.spec.ts @@ -862,12 +862,12 @@ describe.each([ { label: "type1Specific", apply: `'type1Specific'`, - // info: "", + info: "", }, { label: "common", apply: `'common'`, - // info: "", + info: "", }, ], schema: testSchemaConditionalPropertiesOnSameObject, @@ -880,12 +880,12 @@ describe.each([ { label: "type2Specific", apply: `'type2Specific'`, - // info: "", + info: "", }, { label: "common", apply: `'common'`, - // info: "", + info: "", }, ], schema: testSchemaConditionalPropertiesOnSameObject, @@ -898,11 +898,13 @@ describe.each([ { label: "type1", apply: "'type1'", + info: "", type: "string", }, { label: "type2", apply: "'type2'", + info: "", type: "string", }, ], diff --git a/src/features/completion.ts b/src/features/completion.ts index b24226f..ff27b8c 100644 --- a/src/features/completion.ts +++ b/src/features/completion.ts @@ -842,7 +842,7 @@ export class JSONCompletion { type: schema.type?.toString(), ...this.getAppliedValue(schema.const), - info: schema.description, + info: () => this.formatInfo(schema.description ?? ""), }); } @@ -852,7 +852,7 @@ export class JSONCompletion { collector.add({ type: schema.type?.toString(), ...this.getAppliedValue(enm), - info: schema.description, + info: () => this.formatInfo(schema.description ?? ""), }); } } From fefd07faeba2c4f5535adac9cbcaea6e24e257df Mon Sep 17 00:00:00 2001 From: Pinghao Wu Date: Sat, 30 May 2026 22:33:38 +0800 Subject: [PATCH 3/4] fix(completion): do not use renderer if no description Avoid getting a tiny panel with padding only. --- .../__tests__/json-completion.spec.ts | 61 ------------------- src/features/completion.ts | 14 +++-- 2 files changed, 10 insertions(+), 65 deletions(-) diff --git a/src/features/__tests__/json-completion.spec.ts b/src/features/__tests__/json-completion.spec.ts index a583f23..164482a 100644 --- a/src/features/__tests__/json-completion.spec.ts +++ b/src/features/__tests__/json-completion.spec.ts @@ -20,7 +20,6 @@ describe.each([ label: "foo", type: "property", detail: "string", - info: "", template: '"foo": "#{}"', }, ], @@ -41,12 +40,10 @@ describe.each([ label: "oneOfEg2", type: "property", detail: "", - info: "", template: '"oneOfEg2": #{}', }, { detail: "", - info: "", label: "oneOfObject", template: '"oneOfObject": #{}', type: "property", @@ -169,7 +166,6 @@ describe.each([ { type: "property", detail: "object", - info: "", label: "object", template: '"object": {#{}}', }, @@ -177,7 +173,6 @@ describe.each([ template: '"objectWithRef": {#{}}', label: "objectWithRef", detail: "", - info: "", type: "property", }, ], @@ -218,7 +213,6 @@ describe.each([ expectedResults: [ { detail: "string", - info: "", label: "foo", template: '"foo": "#{}"', type: "property", @@ -232,28 +226,24 @@ describe.each([ expectedResults: [ { detail: "string", - info: "", label: "foo", template: '"foo": "#{}"', type: "property", }, { detail: "number", - info: "", label: "bar", template: '"bar": #{0}', type: "property", }, { detail: "string", - info: "", label: "apple", template: '"apple": "#{}"', type: "property", }, { detail: "number", - info: "", label: "banana", template: '"banana": #{0}', type: "property", @@ -268,7 +258,6 @@ describe.each([ expectedResults: [ { detail: "string", - info: "", label: "foo", template: '"foo": "#{}"', type: "property", @@ -283,14 +272,12 @@ describe.each([ { type: "property", detail: "array", - info: "", label: "arrayOfObjects", template: '"arrayOfObjects": [#{}]', }, { type: "property", detail: "array", - info: "", label: "arrayOfOneOf", template: '"arrayOfOneOf": [#{}]', }, @@ -303,14 +290,12 @@ describe.each([ expectedResults: [ { detail: "string", - info: "", label: "foo", template: `"foo": "#{}"`, type: "property", }, { detail: "number", - info: "", label: "bar", template: '"bar": #{0}', type: "property", @@ -324,28 +309,24 @@ describe.each([ expectedResults: [ { detail: "string", - info: "", label: "foo", template: '"foo": "#{}"', type: "property", }, { detail: "number", - info: "", label: "bar", template: '"bar": #{0}', type: "property", }, { detail: "string", - info: "", label: "apple", template: '"apple": "#{}"', type: "property", }, { detail: "number", - info: "", label: "banana", template: '"banana": #{0}', type: "property", @@ -360,14 +341,12 @@ describe.each([ { type: "property", detail: "string", - info: "", label: "foo", template: '"foo": "#{}"', }, { type: "property", detail: "number", - info: "", label: "bar", template: '"bar": #{0}', }, @@ -382,14 +361,12 @@ describe.each([ { type: "property", detail: "string", - info: "", label: "foo", template: '"foo": "#{}"', }, { type: "property", detail: "number", - info: "", label: "bar", template: '"bar": #{0}', }, @@ -404,7 +381,6 @@ describe.each([ { type: "property", detail: "string", - info: "", label: "test1Props", template: '"test1Props": "#{}"', }, @@ -421,7 +397,6 @@ describe.each([ label: "foo", type: "property", detail: "string", - info: "", template: "foo: '#{}'", }, ], @@ -442,12 +417,10 @@ describe.each([ label: "oneOfEg2", type: "property", detail: "", - info: "", template: "'oneOfEg2': #{}", }, { detail: "", - info: "", label: "oneOfObject", template: "'oneOfObject': #{}", type: "property", @@ -544,28 +517,24 @@ describe.each([ { type: "property", detail: "string", - info: "", label: "foo", template: "'foo': '#{}'", }, { type: "property", detail: "number", - info: "", label: "bar", template: "'bar': #{0}", }, { type: "property", detail: "string", - info: "", label: "apple", template: "'apple': '#{}'", }, { type: "property", detail: "number", - info: "", label: "banana", template: "'banana': #{0}", }, @@ -579,7 +548,6 @@ describe.each([ { type: "property", detail: "string", - info: "", label: "test1Props", template: "test1Props: '#{}'", }, @@ -596,7 +564,6 @@ describe.each([ label: "foo", type: "property", detail: "string", - info: "", template: "foo: #{}", }, ], @@ -617,12 +584,10 @@ describe.each([ label: "oneOfEg2", type: "property", detail: "", - info: "", template: "oneOfEg2: #{}", }, { detail: "", - info: "", label: "oneOfObject", template: "oneOfObject: #{}", type: "property", @@ -684,7 +649,6 @@ describe.each([ { type: "property", detail: "object", - info: "", label: "object", template: "object: #{}", }, @@ -692,7 +656,6 @@ describe.each([ template: "objectWithRef: #{}", label: "objectWithRef", detail: "", - info: "", type: "property", }, ], @@ -719,14 +682,12 @@ describe.each([ { type: "property", detail: "number", - info: "", label: "bar", template: "bar: #{0}", }, { type: "property", detail: "number", - info: "", label: "banana", template: "banana: #{0}", }, @@ -740,14 +701,12 @@ describe.each([ { type: "property", detail: "array", - info: "", label: "arrayOfObjects", template: "arrayOfObjects: [#{}]", }, { type: "property", detail: "array", - info: "", label: "arrayOfOneOf", template: "arrayOfOneOf: [#{}]", }, @@ -760,7 +719,6 @@ describe.each([ expectedResults: [ { detail: "string", - info: "", label: "foo", template: "foo: #{}", type: "property", @@ -774,14 +732,12 @@ describe.each([ expectedResults: [ { detail: "number", - info: "", label: "bar", template: "bar: #{0}", type: "property", }, { detail: "number", - info: "", label: "banana", template: "banana: #{0}", type: "property", @@ -796,7 +752,6 @@ describe.each([ { type: "property", detail: "string", - info: "", label: "test1Props", template: "test1Props: #{}", }, @@ -818,7 +773,6 @@ describe.each([ { type: "property", detail: "string", - info: "", label: "type1Prop", template: "type1Prop: '#{}'", }, @@ -833,21 +787,18 @@ describe.each([ { type: "property", detail: "string", - info: "", label: "type1Prop", template: `"type1Prop": '#{}'`, }, { type: "property", detail: "", - info: "", label: "commonEnum", template: `"commonEnum": #{}`, }, { type: "property", detail: "", - info: "", label: "commonEnumWithDifferentValues", template: `"commonEnumWithDifferentValues": #{}`, }, @@ -862,12 +813,10 @@ describe.each([ { label: "type1Specific", apply: `'type1Specific'`, - info: "", }, { label: "common", apply: `'common'`, - info: "", }, ], schema: testSchemaConditionalPropertiesOnSameObject, @@ -880,12 +829,10 @@ describe.each([ { label: "type2Specific", apply: `'type2Specific'`, - info: "", }, { label: "common", apply: `'common'`, - info: "", }, ], schema: testSchemaConditionalPropertiesOnSameObject, @@ -898,13 +845,11 @@ describe.each([ { label: "type1", apply: "'type1'", - info: "", type: "string", }, { label: "type2", apply: "'type2'", - info: "", type: "string", }, ], @@ -918,35 +863,30 @@ describe.each([ { type: "property", detail: "string", - info: "", label: "type", template: `"type": #{}`, }, { type: "property", detail: "string", - info: "", label: "type1Prop", template: `"type1Prop": '#{}'`, }, { type: "property", detail: "", - info: "", label: "commonEnum", template: `"commonEnum": #{}`, }, { type: "property", detail: "", - info: "", label: "commonEnumWithDifferentValues", template: `"commonEnumWithDifferentValues": #{}`, }, { type: "property", detail: "string", - info: "", label: "type2Prop", template: `"type2Prop": '#{}'`, }, @@ -973,7 +913,6 @@ describe.each([ { type: "property", detail: "string", - info: "", label: "type1Prop", template: "type1Prop: '#{}'", }, diff --git a/src/features/completion.ts b/src/features/completion.ts index ff27b8c..be05a00 100644 --- a/src/features/completion.ts +++ b/src/features/completion.ts @@ -353,7 +353,6 @@ export class JSONCompletion { if (properties) { Object.entries(properties).forEach(([key, value]) => { if (typeof value === "object") { - const description = value.description ?? ""; const type = value.type ?? ""; const typeStr = Array.isArray(type) ? type.toString() : type; const completion: Completion = { @@ -368,7 +367,9 @@ export class JSONCompletion { ), type: "property", detail: typeStr, - info: () => this.formatInfo(description), + info: value.description + ? () => this.formatInfo(value.description!) + : undefined, }; collector.add(this.applySnippetCompletion(completion)); } @@ -842,7 +843,9 @@ export class JSONCompletion { type: schema.type?.toString(), ...this.getAppliedValue(schema.const), - info: () => this.formatInfo(schema.description ?? ""), + info: schema.description + ? () => this.formatInfo(schema.description!) + : undefined, }); } @@ -852,7 +855,10 @@ export class JSONCompletion { collector.add({ type: schema.type?.toString(), ...this.getAppliedValue(enm), - info: () => this.formatInfo(schema.description ?? ""), + + info: schema.description + ? () => this.formatInfo(schema.description!) + : undefined, }); } } From ed200b6271483dabf7119c5ccc49cc119d35f072 Mon Sep 17 00:00:00 2001 From: Pinghao Wu Date: Sat, 30 May 2026 22:59:08 +0800 Subject: [PATCH 4/4] chore: add changeset --- .changeset/beige-gorillas-occur.md | 5 +++++ .changeset/lemon-apricots-laugh.md | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 .changeset/beige-gorillas-occur.md create mode 100644 .changeset/lemon-apricots-laugh.md diff --git a/.changeset/beige-gorillas-occur.md b/.changeset/beige-gorillas-occur.md new file mode 100644 index 0000000..ab8830e --- /dev/null +++ b/.changeset/beige-gorillas-occur.md @@ -0,0 +1,5 @@ +--- +"codemirror-json-schema": patch +--- + +Fix description rendering on empty or no description, and enums diff --git a/.changeset/lemon-apricots-laugh.md b/.changeset/lemon-apricots-laugh.md new file mode 100644 index 0000000..6edda2a --- /dev/null +++ b/.changeset/lemon-apricots-laugh.md @@ -0,0 +1,5 @@ +--- +"codemirror-json-schema": minor +--- + +Add formatInfo option to completion to control description rendering